mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various UI fixes
This commit is contained in:
parent
e3a669f489
commit
cfb5d2027a
@ -21,7 +21,6 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
|
||||
|
||||
let buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId)
|
||||
|
||||
let apiId: Int32 = buildConfig.apiId
|
||||
let languagesCategory = "ios"
|
||||
|
||||
let appGroupName = "group.\(baseAppBundleId)"
|
||||
|
@ -19,7 +19,6 @@ class ShareRootController: UIViewController {
|
||||
|
||||
let buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId)
|
||||
|
||||
let apiId: Int32 = buildConfig.apiId
|
||||
let languagesCategory = "ios"
|
||||
|
||||
let appGroupName = "group.\(baseAppBundleId)"
|
||||
|
@ -4614,6 +4614,7 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"ScheduledMessages.DeleteMany" = "Delete Scheduled Messages";
|
||||
"ScheduledMessages.EmptyPlaceholder" = "No scheduled messages here yet...";
|
||||
"ScheduledMessages.BotActionUnavailable" = "This action will become available after the message is published.";
|
||||
"ScheduledMessages.PollUnavailable" = "Voting will become available after the message is published.";
|
||||
|
||||
"Conversation.SendMessage.SetReminder" = "Set a Reminder";
|
||||
|
||||
|
@ -838,7 +838,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode<BotCheckoutEntry>,
|
||||
}
|
||||
|
||||
if let shippingOptions = strongSelf.currentValidatedFormInfo?.shippingOptions, let shippingOptionId = strongSelf.currentShippingOptionId {
|
||||
if let shippingOptionIndex = shippingOptions.index(where: { $0.id == shippingOptionId }) {
|
||||
if let shippingOptionIndex = shippingOptions.firstIndex(where: { $0.id == shippingOptionId }) {
|
||||
for price in shippingOptions[shippingOptionIndex].prices {
|
||||
totalAmount += price.amount
|
||||
|
||||
|
@ -154,6 +154,7 @@ private final class BotCheckoutPasswordAlertContentNode: AlertContentNode {
|
||||
self.textFieldNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(12.0)]
|
||||
self.textFieldNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textFieldNode.textField.isSecureTextEntry = true
|
||||
self.textFieldNode.textField.tintColor = theme.list.itemAccentColor
|
||||
|
||||
super.init()
|
||||
|
||||
|
@ -80,6 +80,7 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate {
|
||||
self.textField.textField.textColor = theme.list.itemPrimaryTextColor
|
||||
self.textField.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: titleFont, textColor: theme.list.itemPlaceholderTextColor)
|
||||
self.textField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textField.textField.tintColor = theme.list.itemAccentColor
|
||||
}
|
||||
|
||||
let leftInset: CGFloat = 16.0
|
||||
@ -97,6 +98,7 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate {
|
||||
self.theme = theme
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.title, font: titleFont, textColor: theme.list.itemPrimaryTextColor)
|
||||
self.textField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textField.textField.tintColor = theme.list.itemAccentColor
|
||||
}
|
||||
|
||||
let leftInset: CGFloat = 16.0
|
||||
|
@ -853,7 +853,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
}
|
||||
|
||||
self.chatListDisplayNode.isEmptyUpdated = { [weak self] isEmpty in
|
||||
if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode, let validLayout = strongSelf.validLayout {
|
||||
if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode, let _ = strongSelf.validLayout {
|
||||
if isEmpty {
|
||||
searchContentNode.updateListVisibleContentOffset(.known(0.0))
|
||||
}
|
||||
|
@ -1402,7 +1402,6 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
let titlePosition = strongSelf.titleNode.position
|
||||
transition.animatePosition(node: strongSelf.titleNode, from: CGPoint(x: titlePosition.x - contentDelta.x, y: titlePosition.y - contentDelta.y))
|
||||
|
||||
let textPosition = strongSelf.textNode.position
|
||||
transition.animatePositionAdditive(node: strongSelf.textNode, offset: CGPoint(x: -contentDelta.x, y: -contentDelta.y))
|
||||
|
||||
let authorPosition = strongSelf.authorNode.position
|
||||
|
@ -275,6 +275,7 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
|
||||
|
||||
if strongSelf.isNodeLoaded {
|
||||
strongSelf.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: item.theme.list.itemPrimaryTextColor]
|
||||
strongSelf.textNode.tintColor = item.theme.list.itemAccentColor
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,6 +223,8 @@ public final class DeviceAccess {
|
||||
subscriber.putNext(.denied)
|
||||
case .notDetermined:
|
||||
subscriber.putNext(.notDetermined)
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
subscriber.putCompletion()
|
||||
return EmptyDisposable
|
||||
@ -333,6 +335,8 @@ public final class DeviceAccess {
|
||||
value = false
|
||||
case .authorized:
|
||||
value = true
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
let _ = cachedMediaLibraryAccessStatus.swap(value)
|
||||
continueWithValue(value)
|
||||
@ -376,7 +380,9 @@ public final class DeviceAccess {
|
||||
}
|
||||
case .notDetermined:
|
||||
completion(true)
|
||||
}
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
case .contacts:
|
||||
let _ = (self.contactsPromise.get()
|
||||
|> take(1)
|
||||
|
@ -63,7 +63,7 @@ final class InstantPageFeedbackNode: ASDisplayNode, InstantPageNode {
|
||||
|
||||
@objc func buttonPressed() {
|
||||
self.resolveDisposable.set((resolvePeerByName(account: self.context.account, name: "previews") |> deliverOnMainQueue).start(next: { [weak self] peerId in
|
||||
if let strongSelf = self, let peerId = peerId, let webPageId = strongSelf.webPage.id?.id {
|
||||
if let strongSelf = self, let _ = peerId, let webPageId = strongSelf.webPage.id?.id {
|
||||
strongSelf.openUrl(InstantPageUrlItem(url: "https://t.me/previews?start=webpage\(webPageId)", webpageId: nil))
|
||||
}
|
||||
}))
|
||||
|
@ -112,7 +112,7 @@ final class InstantPageGalleryFooterContentNode: GalleryFooterContentNode {
|
||||
let sideInset: CGFloat = leftInset + 8.0
|
||||
let topInset: CGFloat = 0.0
|
||||
let bottomInset: CGFloat = 0.0
|
||||
var textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
|
||||
|
||||
var x = sideInset
|
||||
if let hasRTL = self.textNode.cachedLayout?.hasRTL, hasRTL {
|
||||
|
@ -787,12 +787,12 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
|
||||
}
|
||||
|
||||
if requiresScroll {
|
||||
textItem.frame = textItem.frame.offsetBy(dx: 0.0, dy: fabs(topInset))
|
||||
textItem.frame = textItem.frame.offsetBy(dx: 0.0, dy: abs(topInset))
|
||||
for var item in additionalItems {
|
||||
item.frame = item.frame.offsetBy(dx: 0.0, dy: fabs(topInset))
|
||||
item.frame = item.frame.offsetBy(dx: 0.0, dy: abs(topInset))
|
||||
}
|
||||
|
||||
let scrollableItem = InstantPageScrollableTextItem(frame: CGRect(x: 0.0, y: 0.0, width: boundingWidth + horizontalInset * 2.0, height: height + fabs(topInset) + bottomInset), item: textItem, additionalItems: additionalItems, totalWidth: textWidth, horizontalInset: horizontalInset, rtl: textItem.containsRTL)
|
||||
let scrollableItem = InstantPageScrollableTextItem(frame: CGRect(x: 0.0, y: 0.0, width: boundingWidth + horizontalInset * 2.0, height: height + abs(topInset) + bottomInset), item: textItem, additionalItems: additionalItems, totalWidth: textWidth, horizontalInset: horizontalInset, rtl: textItem.containsRTL)
|
||||
items.append(scrollableItem)
|
||||
} else {
|
||||
items.append(contentsOf: additionalItems)
|
||||
|
@ -523,13 +523,11 @@ open class ItemListControllerNode<Entry: ItemListNodeEntry>: ASDisplayNode, UISc
|
||||
}
|
||||
if updatedFocusItemTag {
|
||||
if let focusItemTag = focusItemTag {
|
||||
var applied = false
|
||||
strongSelf.listNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ItemListItemNode {
|
||||
if let itemTag = itemNode.tag {
|
||||
if itemTag.isEqual(to: focusItemTag) {
|
||||
if let focusableNode = itemNode as? ItemListItemFocusableNode {
|
||||
applied = true
|
||||
focusableNode.focus()
|
||||
}
|
||||
}
|
||||
|
@ -208,6 +208,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
|
||||
if strongSelf.isNodeLoaded {
|
||||
strongSelf.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: item.theme.list.itemPrimaryTextColor]
|
||||
strongSelf.textNode.tintColor = item.theme.list.itemAccentColor
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,6 +154,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
if let item = self.item {
|
||||
self.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor
|
||||
self.textNode.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textNode.textField.tintColor = item.theme.list.itemAccentColor
|
||||
self.textNode.textField.accessibilityHint = item.placeholder
|
||||
}
|
||||
self.textNode.clipsToBounds = true
|
||||
@ -210,6 +211,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
|
||||
strongSelf.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor
|
||||
strongSelf.textNode.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
strongSelf.textNode.textField.tintColor = item.theme.list.itemAccentColor
|
||||
}
|
||||
|
||||
let _ = titleApply()
|
||||
|
@ -163,7 +163,7 @@ When combined with the autoreverses property, a singular animation is effectivel
|
||||
|
||||
/**
|
||||
@abstract Returns an array containing the keys of all animations currently attached to the receiver.
|
||||
@param The order of keys reflects the order in which animations will be applied.
|
||||
@discussion The order of keys reflects the order in which animations will be applied.
|
||||
*/
|
||||
- (NSArray *)pop_animationKeys;
|
||||
|
||||
|
@ -1330,8 +1330,9 @@ static UIImage *startImage = nil;
|
||||
{
|
||||
NSTimeInterval timestamp = timestampVal.doubleValue;
|
||||
NSNumber *closestTimestamp = [self closestTimestampForTimestamp:timestamp timestamps:thumbnailTimestamps start:i finalIndex:&i];
|
||||
|
||||
[thumbnails addObject:_thumbnails[closestTimestamp]];
|
||||
if (closestTimestamp != nil) {
|
||||
[thumbnails addObject:_thumbnails[closestTimestamp]];
|
||||
}
|
||||
}];
|
||||
|
||||
return thumbnails;
|
||||
@ -1339,6 +1340,9 @@ static UIImage *startImage = nil;
|
||||
|
||||
- (NSNumber *)closestTimestampForTimestamp:(NSTimeInterval)timestamp timestamps:(NSArray *)timestamps start:(NSUInteger)start finalIndex:(NSUInteger *)finalIndex
|
||||
{
|
||||
if (start >= timestamps.count) {
|
||||
return nil;
|
||||
}
|
||||
NSTimeInterval leftTimestamp = [timestamps[start - 1] doubleValue];
|
||||
NSTimeInterval rightTimestamp = [timestamps[start] doubleValue];
|
||||
|
||||
|
@ -183,7 +183,7 @@ public func legacyAssetPickerItemGenerator() -> ((Any?, String?, [Any]?, String?
|
||||
return result
|
||||
}
|
||||
} else if (dict["type"] as! NSString) == "video" {
|
||||
var thumbnail = dict["previewImage"] as? UIImage
|
||||
let thumbnail = dict["previewImage"] as? UIImage
|
||||
var asFile = false
|
||||
if let document = dict["document"] as? NSNumber, document.boolValue {
|
||||
asFile = true
|
||||
|
@ -503,21 +503,10 @@ open class LegacyController: ViewController, PresentableController {
|
||||
switch self.presentation {
|
||||
case .modal:
|
||||
self.controllerNode.animateModalOut { [weak self] in
|
||||
if let controller = self?.legacyController as? TGViewController {
|
||||
//controller.didDismiss()
|
||||
} else if let controller = self?.legacyController as? TGNavigationController {
|
||||
//controller.didDismiss()
|
||||
}
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: completion)
|
||||
}
|
||||
case .custom:
|
||||
if let controller = self.legacyController as? TGViewController {
|
||||
//controller.didDismiss()
|
||||
} else if let controller = self.legacyController as? TGNavigationController {
|
||||
//controller.didDismiss()
|
||||
}
|
||||
self.presentingViewController?.dismiss(animated: false, completion: completion)
|
||||
|
||||
case .navigation:
|
||||
break
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
|
||||
return { [weak self] account, theme, peer, liveActive in
|
||||
let backgroundImage: UIImage?
|
||||
var hasPulse = false
|
||||
if let peer = peer {
|
||||
if let _ = peer {
|
||||
backgroundImage = avatarBackgroundImage
|
||||
|
||||
if let liveActive = liveActive {
|
||||
|
@ -185,6 +185,7 @@ final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate {
|
||||
self.textFieldNode.textField.tintColor = self.accentColor
|
||||
self.textFieldNode.textField.keyboardAppearance = self.keyboardAppearance
|
||||
self.textFieldNode.textField.keyboardType = self.fieldType.keyboardType
|
||||
self.textFieldNode.textField.tintColor = self.accentColor
|
||||
|
||||
if self.useCustomNumpad {
|
||||
switch self.fieldType {
|
||||
|
@ -144,6 +144,7 @@ final class FormControllerTextInputItemNode: FormBlockItemNode<FormControllerTex
|
||||
}
|
||||
|
||||
self.textField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textField.textField.tintColor = theme.list.itemAccentColor
|
||||
|
||||
let attributedPlaceholder = NSAttributedString(string: item.placeholder, font: textFont, textColor: theme.list.itemPlaceholderTextColor)
|
||||
if !(self.textField.textField.attributedPlaceholder?.isEqual(to: attributedPlaceholder) ?? false) {
|
||||
|
@ -163,7 +163,6 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
|
||||
|
||||
let wrappingContentRect = CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight), size: CGSize(width: layout.size.width, height: layout.size.height - insets.bottom - navigationBarHeight))
|
||||
let contentRect = CGRect(origin: CGPoint(), size: wrappingContentRect.size)
|
||||
let overscrollY = self.scrollNode.view.bounds.minY
|
||||
transition.updateFrame(node: self.scrollNode, frame: wrappingContentRect)
|
||||
|
||||
if let contentNode = self.contentNode {
|
||||
@ -608,7 +607,7 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
|
||||
}
|
||||
|
||||
let completionImpl: (SecureIdDocumentFormRequestedData) -> Void = { [weak self] requestedData in
|
||||
guard let strongSelf = self, let state = strongSelf.state, let verificationState = state.verificationState, case let .verified(context) = verificationState, let formData = form.formData, let validLayout = strongSelf.validLayout?.0 else {
|
||||
guard let strongSelf = self, let state = strongSelf.state, let verificationState = state.verificationState, case .verified = verificationState, let formData = form.formData, let validLayout = strongSelf.validLayout?.0 else {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,7 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
|
||||
self.inputField.textField.textColor = theme.list.freeInputField.primaryColor
|
||||
self.inputField.textField.attributedPlaceholder = NSAttributedString(string: hint.isEmpty ? strings.LoginPassword_PasswordPlaceholder : hint, font: passwordFont, textColor: theme.list.freeInputField.placeholderColor)
|
||||
self.inputField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.inputField.textField.tintColor = theme.list.itemAccentColor
|
||||
|
||||
self.buttonNode = HighlightableButtonNode()
|
||||
|
||||
|
@ -2953,7 +2953,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
if let _ = innerState.documents.index(where: { $0.id == document.id }) {
|
||||
if let _ = innerState.documents.firstIndex(where: { $0.id == document.id }) {
|
||||
for itemDocument in innerState.documents {
|
||||
entries.append(SecureIdDocumentGalleryEntry(index: Int32(index), resource: itemDocument.resource, location: SecureIdDocumentGalleryEntryLocation(position: Int32(index), totalCount: totalCount), error: ""))
|
||||
if document.id == itemDocument.id {
|
||||
@ -2962,7 +2962,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
if let _ = innerState.translations.index(where: { $0.id == document.id }) {
|
||||
if let _ = innerState.translations.firstIndex(where: { $0.id == document.id }) {
|
||||
for itemDocument in innerState.translations {
|
||||
entries.append(SecureIdDocumentGalleryEntry(index: Int32(index), resource: itemDocument.resource, location: SecureIdDocumentGalleryEntryLocation(position: Int32(index), totalCount: totalCount), error: ""))
|
||||
if document.id == itemDocument.id {
|
||||
|
@ -123,8 +123,10 @@ final class SecureIdValueFormPhoneItemNode: FormBlockItemNode<SecureIdValueFormP
|
||||
self.phoneInputNode.countryCodeField.textField.textColor = theme.list.itemPrimaryTextColor
|
||||
self.phoneInputNode.numberField.textField.textColor = theme.list.itemPrimaryTextColor
|
||||
|
||||
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor
|
||||
self.phoneInputNode.numberField.textField.tintColor = theme.list.itemAccentColor
|
||||
|
||||
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.numberField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,7 @@ final class SetupTwoStepVerificationContentNode: ASDisplayNode, UITextFieldDeleg
|
||||
self.inputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(22.0), textColor: theme.list.itemPlaceholderTextColor)
|
||||
self.inputNode.textField.textAlignment = .center
|
||||
self.inputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.inputNode.textField.tintColor = theme.list.itemAccentColor
|
||||
switch inputType {
|
||||
case .password:
|
||||
self.inputNode.textField.isSecureTextEntry = true
|
||||
@ -127,6 +128,7 @@ final class SetupTwoStepVerificationContentNode: ASDisplayNode, UITextFieldDeleg
|
||||
self.theme = presentationData.theme
|
||||
self.inputNode.textField.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.inputSeparator.backgroundColor = self.theme.list.itemPlainSeparatorColor
|
||||
self.inputNode.textField.tintColor = self.theme.list.itemAccentColor
|
||||
}
|
||||
|
||||
func updateIsEnabled(_ isEnabled: Bool) {
|
||||
|
@ -178,7 +178,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
}
|
||||
self.imageNode.setSignal(chatAvatarGalleryPhoto(account: self.context.account, representations: representations), dispatchOnDisplayLink: false)
|
||||
self.zoomableContent = (largestSize.dimensions, self.imageNode)
|
||||
if let largestIndex = representations.index(where: { $0.representation == largestSize }) {
|
||||
if let largestIndex = representations.firstIndex(where: { $0.representation == largestSize }) {
|
||||
self.fetchDisposable.set(fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, reference: representations[largestIndex].reference).start())
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
strongSelf.statusNode.isHidden = false
|
||||
strongSelf.statusNodeContainer.isUserInteractionEnabled = true
|
||||
strongSelf.statusNode.transitionToState(.download(.white), completion: {})
|
||||
case let .Fetching(isActive, progress):
|
||||
case let .Fetching(_, progress):
|
||||
strongSelf.statusNode.isHidden = false
|
||||
strongSelf.statusNodeContainer.isUserInteractionEnabled = true
|
||||
let adjustedProgress = max(progress, 0.027)
|
||||
@ -345,7 +345,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
representations = imageRepresentations
|
||||
}
|
||||
|
||||
if let largestIndex = representations.index(where: { $0.representation == largestSize }) {
|
||||
if let largestIndex = representations.firstIndex(where: { $0.representation == largestSize }) {
|
||||
self.fetchDisposable.set(fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, reference: representations[largestIndex].reference).start())
|
||||
}
|
||||
default:
|
||||
|
@ -80,11 +80,12 @@ private final class ChannelOwnershipTransferPasswordFieldNode: ASDisplayNode, UI
|
||||
self.textInputNode.textField.textColor = self.theme.list.itemPrimaryTextColor
|
||||
self.textInputNode.textField.isSecureTextEntry = true
|
||||
self.textInputNode.textField.returnKeyType = .done
|
||||
self.textInputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textInputNode.textField.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textInputNode.clipsToBounds = true
|
||||
self.textInputNode.textField.delegate = self
|
||||
self.textInputNode.textField.addTarget(self, action: #selector(self.textFieldTextChanged(_:)), for: .editingChanged)
|
||||
self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
|
||||
self.textInputNode.textField.tintColor = self.theme.list.itemAccentColor
|
||||
}
|
||||
|
||||
func updateTheme(_ theme: PresentationTheme) {
|
||||
@ -94,6 +95,7 @@ private final class ChannelOwnershipTransferPasswordFieldNode: ASDisplayNode, UI
|
||||
self.textInputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textInputNode.textField.textColor = theme.list.itemPrimaryTextColor
|
||||
self.textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(14.0), NSAttributedString.Key.foregroundColor: theme.actionSheet.inputTextColor]
|
||||
self.textInputNode.textField.tintColor = theme.list.itemAccentColor
|
||||
self.placeholderNode.attributedText = NSAttributedString(string: self.placeholderNode.attributedText?.string ?? "", font: Font.regular(14.0), textColor: theme.actionSheet.inputPlaceholderColor)
|
||||
}
|
||||
|
||||
|
@ -184,6 +184,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
|
||||
if let item = self.item {
|
||||
self.phoneNode.numberField?.textField.textColor = item.theme.list.itemPrimaryTextColor
|
||||
self.phoneNode.numberField?.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.phoneNode.numberField?.textField.tintColor = item.theme.list.itemAccentColor
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,6 +234,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
|
||||
|
||||
strongSelf.phoneNode.numberField?.textField.textColor = updatedTheme.list.itemPrimaryTextColor
|
||||
strongSelf.phoneNode.numberField?.textField.keyboardAppearance = updatedTheme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
strongSelf.phoneNode.numberField?.textField.tintColor = item.theme.list.itemAccentColor
|
||||
|
||||
strongSelf.clearButton.setImage(generateClearIcon(color: updatedTheme.list.inputClearButtonColor), for: [])
|
||||
}
|
||||
|
@ -805,45 +805,33 @@ public func chatMessagePhotoInternal(photoData: Signal<Tuple3<Data?, Data?, Bool
|
||||
let thumbnailSize = CGSize(width: fullSizeImage.width, height: fullSizeImage.height)
|
||||
|
||||
var sideBlurredImage: UIImage?
|
||||
if true {
|
||||
let initialThumbnailContextFittingSize = fittedSize.fitted(CGSize(width: 100.0, height: 100.0))
|
||||
|
||||
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize)
|
||||
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
|
||||
thumbnailContext.withFlippedContext { c in
|
||||
c.interpolationQuality = .none
|
||||
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
|
||||
}
|
||||
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
||||
|
||||
var thumbnailContextFittingSize = CGSize(width: floor(arguments.drawingSize.width * 0.5), height: floor(arguments.drawingSize.width * 0.5))
|
||||
if thumbnailContextFittingSize.width < 150.0 || thumbnailContextFittingSize.height < 150.0 {
|
||||
thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0))
|
||||
}
|
||||
|
||||
if thumbnailContextFittingSize.width > thumbnailContextSize.width {
|
||||
let additionalContextSize = thumbnailContextFittingSize
|
||||
let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0)
|
||||
additionalBlurContext.withFlippedContext { c in
|
||||
c.interpolationQuality = .default
|
||||
if let image = thumbnailContext.generateImage()?.cgImage {
|
||||
c.draw(image, in: CGRect(origin: CGPoint(), size: additionalContextSize))
|
||||
}
|
||||
let initialThumbnailContextFittingSize = fittedSize.fitted(CGSize(width: 100.0, height: 100.0))
|
||||
|
||||
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize)
|
||||
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
|
||||
thumbnailContext.withFlippedContext { c in
|
||||
c.interpolationQuality = .none
|
||||
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
|
||||
}
|
||||
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
||||
|
||||
var thumbnailContextFittingSize = CGSize(width: floor(arguments.drawingSize.width * 0.5), height: floor(arguments.drawingSize.width * 0.5))
|
||||
if thumbnailContextFittingSize.width < 150.0 || thumbnailContextFittingSize.height < 150.0 {
|
||||
thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0))
|
||||
}
|
||||
|
||||
if thumbnailContextFittingSize.width > thumbnailContextSize.width {
|
||||
let additionalContextSize = thumbnailContextFittingSize
|
||||
let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0)
|
||||
additionalBlurContext.withFlippedContext { c in
|
||||
c.interpolationQuality = .default
|
||||
if let image = thumbnailContext.generateImage()?.cgImage {
|
||||
c.draw(image, in: CGRect(origin: CGPoint(), size: additionalContextSize))
|
||||
}
|
||||
imageFastBlur(Int32(additionalContextSize.width), Int32(additionalContextSize.height), Int32(additionalBlurContext.bytesPerRow), additionalBlurContext.bytes)
|
||||
sideBlurredImage = additionalBlurContext.generateImage()
|
||||
} else {
|
||||
sideBlurredImage = thumbnailContext.generateImage()
|
||||
}
|
||||
imageFastBlur(Int32(additionalContextSize.width), Int32(additionalContextSize.height), Int32(additionalBlurContext.bytesPerRow), additionalBlurContext.bytes)
|
||||
sideBlurredImage = additionalBlurContext.generateImage()
|
||||
} else {
|
||||
let thumbnailContextSize = thumbnailSize.aspectFitted(CGSize(width: 74.0, height: 74.0))
|
||||
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
|
||||
thumbnailContext.withFlippedContext { c in
|
||||
c.interpolationQuality = .none
|
||||
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
|
||||
}
|
||||
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
||||
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
||||
sideBlurredImage = thumbnailContext.generateImage()
|
||||
}
|
||||
|
||||
@ -1230,7 +1218,7 @@ public func chatSecretPhoto(account: Account, photoReference: ImageMediaReferenc
|
||||
}
|
||||
|
||||
private func avatarGalleryThumbnailDatas(postbox: Postbox, representations: [ImageRepresentationWithReference], fullRepresentationSize: CGSize = CGSize(width: 1280.0, height: 1280.0), autoFetchFullSize: Bool = false) -> Signal<Tuple3<Data?, Data?, Bool>, NoError> {
|
||||
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = imageRepresentationLargerThan(representations.map({ $0.representation }), size: fullRepresentationSize), let smallestIndex = representations.index(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.index(where: { $0.representation == largestRepresentation }) {
|
||||
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = imageRepresentationLargerThan(representations.map({ $0.representation }), size: fullRepresentationSize), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
|
||||
let maybeFullSize = postbox.mediaBox.resourceData(largestRepresentation.resource)
|
||||
|
||||
let signal = maybeFullSize
|
||||
@ -1670,45 +1658,33 @@ public func internalMediaGridMessageVideo(postbox: Postbox, videoReference: File
|
||||
if let fullSizeImage = blurSourceImage {
|
||||
var sideBlurredImage: UIImage?
|
||||
let thumbnailSize = CGSize(width: fullSizeImage.width, height: fullSizeImage.height)
|
||||
if true {
|
||||
let initialThumbnailContextFittingSize = drawingSize.fitted(CGSize(width: 100.0, height: 100.0))
|
||||
|
||||
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize)
|
||||
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
|
||||
thumbnailContext.withFlippedContext { c in
|
||||
c.interpolationQuality = .none
|
||||
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
|
||||
}
|
||||
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
||||
|
||||
var thumbnailContextFittingSize = CGSize(width: floor(arguments.drawingSize.width * 0.5), height: floor(arguments.drawingSize.width * 0.5))
|
||||
if thumbnailContextFittingSize.width < 150.0 || thumbnailContextFittingSize.height < 150.0 {
|
||||
thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0))
|
||||
}
|
||||
|
||||
if thumbnailContextFittingSize.width > thumbnailContextSize.width {
|
||||
let additionalContextSize = thumbnailContextFittingSize
|
||||
let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0)
|
||||
additionalBlurContext.withFlippedContext { c in
|
||||
c.interpolationQuality = .default
|
||||
if let image = thumbnailContext.generateImage()?.cgImage {
|
||||
c.draw(image, in: CGRect(origin: CGPoint(), size: additionalContextSize))
|
||||
}
|
||||
let initialThumbnailContextFittingSize = drawingSize.fitted(CGSize(width: 100.0, height: 100.0))
|
||||
|
||||
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize)
|
||||
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
|
||||
thumbnailContext.withFlippedContext { c in
|
||||
c.interpolationQuality = .none
|
||||
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
|
||||
}
|
||||
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
||||
|
||||
var thumbnailContextFittingSize = CGSize(width: floor(arguments.drawingSize.width * 0.5), height: floor(arguments.drawingSize.width * 0.5))
|
||||
if thumbnailContextFittingSize.width < 150.0 || thumbnailContextFittingSize.height < 150.0 {
|
||||
thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0))
|
||||
}
|
||||
|
||||
if thumbnailContextFittingSize.width > thumbnailContextSize.width {
|
||||
let additionalContextSize = thumbnailContextFittingSize
|
||||
let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0)
|
||||
additionalBlurContext.withFlippedContext { c in
|
||||
c.interpolationQuality = .default
|
||||
if let image = thumbnailContext.generateImage()?.cgImage {
|
||||
c.draw(image, in: CGRect(origin: CGPoint(), size: additionalContextSize))
|
||||
}
|
||||
imageFastBlur(Int32(additionalContextSize.width), Int32(additionalContextSize.height), Int32(additionalBlurContext.bytesPerRow), additionalBlurContext.bytes)
|
||||
sideBlurredImage = additionalBlurContext.generateImage()
|
||||
} else {
|
||||
sideBlurredImage = thumbnailContext.generateImage()
|
||||
}
|
||||
imageFastBlur(Int32(additionalContextSize.width), Int32(additionalContextSize.height), Int32(additionalBlurContext.bytesPerRow), additionalBlurContext.bytes)
|
||||
sideBlurredImage = additionalBlurContext.generateImage()
|
||||
} else {
|
||||
let thumbnailContextSize = thumbnailSize.aspectFitted(CGSize(width: 74.0, height: 74.0))
|
||||
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
|
||||
thumbnailContext.withFlippedContext { c in
|
||||
c.interpolationQuality = .none
|
||||
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
|
||||
}
|
||||
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
||||
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
||||
sideBlurredImage = thumbnailContext.generateImage()
|
||||
}
|
||||
|
||||
@ -2307,7 +2283,7 @@ public func instantPageImageFile(account: Account, fileReference: FileMediaRefer
|
||||
}
|
||||
|
||||
private func avatarGalleryPhotoDatas(account: Account, fileReference: FileMediaReference? = nil, representations: [ImageRepresentationWithReference], autoFetchFullSize: Bool = false) -> Signal<Tuple3<Data?, Data?, Bool>, NoError> {
|
||||
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.index(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.index(where: { $0.representation == largestRepresentation }) {
|
||||
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
|
||||
|
||||
let maybeFullSize = account.postbox.mediaBox.resourceData(largestRepresentation.resource)
|
||||
|
||||
|
@ -103,4 +103,5 @@ public protocol ItemCollectionItem: PostboxCoding {
|
||||
public enum ItemCollectionSearchQuery {
|
||||
case exact(ValueBoxKey)
|
||||
case matching([ValueBoxKey])
|
||||
case any([ValueBoxKey])
|
||||
}
|
||||
|
@ -229,6 +229,8 @@ final class ItemCollectionItemTable: Table {
|
||||
references = self.reverseIndexTable.exactReferences(namespace: ReverseIndexNamespace(namespace), token: token)
|
||||
case let .matching(tokens):
|
||||
references = Array(self.reverseIndexTable.matchingReferences(namespace: ReverseIndexNamespace(namespace), tokens: tokens))
|
||||
case let .any(tokens):
|
||||
references = Array(self.reverseIndexTable.matchingReferences(namespace: ReverseIndexNamespace(namespace), tokens: tokens, union: true))
|
||||
}
|
||||
var resultsByCollectionId: [ItemCollectionId: [(ItemCollectionItemIndex, ItemCollectionItem)]] = [:]
|
||||
for reference in references {
|
||||
|
@ -426,8 +426,8 @@ final class MessageHistoryTable: Table {
|
||||
self.processIndexOperations(peerId, operations: operations, processedOperationsByPeerId: &operationsByPeerId, updatedMedia: &updatedMedia, unsentMessageOperations: &unsentMessageOperations, updatedPeerReadStateOperations: &updatedPeerReadStateOperations, globalTagsOperations: &globalTagsOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, localTagsOperations: &localTagsOperations)
|
||||
}
|
||||
|
||||
func clearHistory(peerId: PeerId, operationsByPeerId: inout [PeerId: [MessageHistoryOperation]], updatedMedia: inout [MediaId: Media?], unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedPeerReadStateOperations: inout [PeerId: PeerReadStateSynchronizationOperation?], globalTagsOperations: inout [GlobalMessageHistoryTagsOperation], pendingActionsOperations: inout [PendingMessageActionsOperation], updatedMessageActionsSummaries: inout [PendingMessageActionsSummaryKey: Int32], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation]) {
|
||||
let indices = self.allMessageIndices(peerId: peerId)
|
||||
func clearHistory(peerId: PeerId, namespaces: MessageIdNamespaces, operationsByPeerId: inout [PeerId: [MessageHistoryOperation]], updatedMedia: inout [MediaId: Media?], unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedPeerReadStateOperations: inout [PeerId: PeerReadStateSynchronizationOperation?], globalTagsOperations: inout [GlobalMessageHistoryTagsOperation], pendingActionsOperations: inout [PendingMessageActionsOperation], updatedMessageActionsSummaries: inout [PendingMessageActionsSummaryKey: Int32], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation]) {
|
||||
let indices = self.allMessageIndices(peerId: peerId).filter { namespaces.contains($0.id.namespace) }
|
||||
self.removeMessages(indices.map { $0.id }, operationsByPeerId: &operationsByPeerId, updatedMedia: &updatedMedia, unsentMessageOperations: &unsentMessageOperations, updatedPeerReadStateOperations: &updatedPeerReadStateOperations, globalTagsOperations: &globalTagsOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, localTagsOperations: &localTagsOperations)
|
||||
}
|
||||
|
||||
|
@ -86,9 +86,9 @@ public final class Transaction {
|
||||
self.postbox?.withAllMessages(peerId: peerId, namespace: namespace, f)
|
||||
}
|
||||
|
||||
public func clearHistory(_ peerId: PeerId) {
|
||||
public func clearHistory(_ peerId: PeerId, namespaces: MessageIdNamespaces) {
|
||||
assert(!self.disposed)
|
||||
self.postbox?.clearHistory(peerId)
|
||||
self.postbox?.clearHistory(peerId, namespaces: namespaces)
|
||||
}
|
||||
|
||||
public func removeAllMessagesWithAuthor(_ peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) {
|
||||
@ -1519,9 +1519,9 @@ public final class Postbox {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func clearHistory(_ peerId: PeerId) {
|
||||
self.messageHistoryTable.clearHistory(peerId: peerId, operationsByPeerId: &self.currentOperationsByPeerId, updatedMedia: &self.currentUpdatedMedia, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations, globalTagsOperations: &self.currentGlobalTagsOperations, pendingActionsOperations: &self.currentPendingMessageActionsOperations, updatedMessageActionsSummaries: &self.currentUpdatedMessageActionsSummaries, updatedMessageTagSummaries: &self.currentUpdatedMessageTagSummaries, invalidateMessageTagSummaries: &self.currentInvalidateMessageTagSummaries, localTagsOperations: &self.currentLocalTagsOperations)
|
||||
for namespace in self.messageHistoryHoleIndexTable.existingNamespaces(peerId: peerId, holeSpace: .everywhere) {
|
||||
fileprivate func clearHistory(_ peerId: PeerId, namespaces: MessageIdNamespaces) {
|
||||
self.messageHistoryTable.clearHistory(peerId: peerId, namespaces: namespaces, operationsByPeerId: &self.currentOperationsByPeerId, updatedMedia: &self.currentUpdatedMedia, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations, globalTagsOperations: &self.currentGlobalTagsOperations, pendingActionsOperations: &self.currentPendingMessageActionsOperations, updatedMessageActionsSummaries: &self.currentUpdatedMessageActionsSummaries, updatedMessageTagSummaries: &self.currentUpdatedMessageTagSummaries, invalidateMessageTagSummaries: &self.currentInvalidateMessageTagSummaries, localTagsOperations: &self.currentLocalTagsOperations)
|
||||
for namespace in self.messageHistoryHoleIndexTable.existingNamespaces(peerId: peerId, holeSpace: .everywhere) where namespaces.contains(namespace) {
|
||||
self.messageHistoryHoleIndexTable.remove(peerId: peerId, namespace: namespace, space: .everywhere, range: 1 ... Int32.max - 1, operations: &self.currentPeerHoleOperations)
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ final class ReverseIndexReferenceTable<T: ReverseIndexReference>: Table {
|
||||
}
|
||||
}
|
||||
|
||||
func matchingReferences(namespace: ReverseIndexNamespace, tokens: [ValueBoxKey]) -> Set<T> {
|
||||
func matchingReferences(namespace: ReverseIndexNamespace, tokens: [ValueBoxKey], union: Bool = false) -> Set<T> {
|
||||
var references: Set<T>?
|
||||
for token in tokens {
|
||||
if let references = references, references.isEmpty {
|
||||
@ -208,7 +208,11 @@ final class ReverseIndexReferenceTable<T: ReverseIndexReference>: Table {
|
||||
return true
|
||||
}, limit: 0)
|
||||
if let previousReferences = references {
|
||||
references = previousReferences.intersection(currentReferences)
|
||||
if union {
|
||||
references = previousReferences.union(currentReferences)
|
||||
} else {
|
||||
references = previousReferences.intersection(currentReferences)
|
||||
}
|
||||
} else {
|
||||
references = currentReferences
|
||||
}
|
||||
|
@ -398,6 +398,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
||||
self.clearButton.setImage(generateClearIcon(color: theme.inputClear), for: [])
|
||||
self.iconNode.image = generateLoupeIcon(color: theme.inputIcon)
|
||||
self.textField.keyboardAppearance = theme.keyboard.keyboardAppearance
|
||||
self.textField.tintColor = theme.accent
|
||||
|
||||
if let activityIndicator = self.activityIndicator {
|
||||
activityIndicator.type = .custom(theme.inputIcon, 13.0, 1.0, false)
|
||||
|
@ -128,8 +128,10 @@ final class ChangePhoneNumberControllerNode: ASDisplayNode {
|
||||
self.phoneInputNode = PhoneInputNode(fontSize: 17.0)
|
||||
self.phoneInputNode.countryCodeField.textField.textColor = self.presentationData.theme.list.itemPrimaryTextColor
|
||||
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = self.presentationData.theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.countryCodeField.textField.tintColor = self.presentationData.theme.list.itemAccentColor
|
||||
self.phoneInputNode.numberField.textField.textColor = self.presentationData.theme.list.itemPrimaryTextColor
|
||||
self.phoneInputNode.numberField.textField.keyboardAppearance = self.presentationData.theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.numberField.textField.tintColor = self.presentationData.theme.list.itemAccentColor
|
||||
|
||||
super.init()
|
||||
|
||||
|
@ -340,7 +340,7 @@ public func proxySettingsController(accountManager: AccountManager, postbox: Pos
|
||||
let _ = updateProxySettingsInteractively(accountManager: accountManager, { current in
|
||||
var current = current
|
||||
if current.activeServer != server {
|
||||
if let _ = current.servers.index(of: server) {
|
||||
if let _ = current.servers.firstIndex(of: server) {
|
||||
current.activeServer = server
|
||||
current.enabled = true
|
||||
}
|
||||
@ -352,7 +352,7 @@ public func proxySettingsController(accountManager: AccountManager, postbox: Pos
|
||||
}, removeServer: { server in
|
||||
let _ = updateProxySettingsInteractively(accountManager: accountManager, { current in
|
||||
var current = current
|
||||
if let index = current.servers.index(of: server) {
|
||||
if let index = current.servers.firstIndex(of: server) {
|
||||
current.servers.remove(at: index)
|
||||
if current.activeServer == server {
|
||||
current.activeServer = nil
|
||||
@ -462,7 +462,7 @@ public func proxySettingsController(accountManager: AccountManager, postbox: Pos
|
||||
|
||||
let _ = updateProxySettingsInteractively(accountManager: accountManager, { current in
|
||||
var current = current
|
||||
if let index = current.servers.index(of: fromServer) {
|
||||
if let index = current.servers.firstIndex(of: fromServer) {
|
||||
current.servers.remove(at: index)
|
||||
}
|
||||
if let referenceServer = referenceServer {
|
||||
|
@ -384,7 +384,7 @@ private final class ProxyServerActionItemNode: ActionSheetItemNode {
|
||||
updateProxySettingsInteractively(transaction: transaction, { settings in
|
||||
currentSettings = settings
|
||||
var settings = settings
|
||||
if let index = settings.servers.index(of: proxyServerSettings) {
|
||||
if let index = settings.servers.firstIndex(of: proxyServerSettings) {
|
||||
settings.servers[index] = proxyServerSettings
|
||||
settings.activeServer = proxyServerSettings
|
||||
} else {
|
||||
|
@ -343,7 +343,7 @@ func proxyServerSettingsController(theme: PresentationTheme, strings: Presentati
|
||||
let _ = (updateProxySettingsInteractively(accountManager: accountManager, { settings in
|
||||
var settings = settings
|
||||
if let currentSettings = currentSettings {
|
||||
if let index = settings.servers.index(of: currentSettings) {
|
||||
if let index = settings.servers.firstIndex(of: currentSettings) {
|
||||
settings.servers[index] = proxyServerSettings
|
||||
if settings.activeServer == currentSettings {
|
||||
settings.activeServer = proxyServerSettings
|
||||
@ -375,7 +375,6 @@ func proxyServerSettingsController(theme: PresentationTheme, strings: Presentati
|
||||
dismissImpl = { [weak controller] in
|
||||
let _ = controller?.dismiss()
|
||||
}
|
||||
|
||||
shareImpl = { [weak controller] in
|
||||
let state = stateValue.with { $0 }
|
||||
guard let server = proxyServerSettings(with: state), let strongController = controller else {
|
||||
@ -383,6 +382,7 @@ func proxyServerSettingsController(theme: PresentationTheme, strings: Presentati
|
||||
}
|
||||
|
||||
let link = shareLink(for: server)
|
||||
controller?.view.endEditing(true)
|
||||
if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
|
||||
let controller = ShareProxyServerActionSheetController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, link: link)
|
||||
presentImpl?(controller, nil)
|
||||
|
@ -344,7 +344,7 @@ private func recentSessionsControllerEntries(presentationData: PresentationData,
|
||||
if !sessionsState.sessions.isEmpty {
|
||||
var existingSessionIds = Set<Int64>()
|
||||
entries.append(.currentSessionHeader(presentationData.theme, presentationData.strings.AuthSessions_CurrentSession))
|
||||
if let index = sessionsState.sessions.index(where: { $0.hash == 0 }) {
|
||||
if let index = sessionsState.sessions.firstIndex(where: { $0.hash == 0 }) {
|
||||
existingSessionIds.insert(sessionsState.sessions[index].hash)
|
||||
entries.append(.currentSession(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, sessionsState.sessions[index]))
|
||||
}
|
||||
|
@ -112,6 +112,7 @@ final class WallpaperColorPanelNode: ASDisplayNode, UITextFieldDelegate {
|
||||
self.textFieldNode.textField.delegate = self
|
||||
self.textFieldNode.textField.addTarget(self, action: #selector(self.textFieldTextChanged(_:)), for: .editingChanged)
|
||||
self.textFieldNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
|
||||
self.textFieldNode.textField.tintColor = self.theme.list.itemAccentColor
|
||||
}
|
||||
|
||||
func updateTheme(_ theme: PresentationTheme) {
|
||||
@ -123,6 +124,7 @@ final class WallpaperColorPanelNode: ASDisplayNode, UITextFieldDelegate {
|
||||
|
||||
self.textFieldNode.textField.textColor = self.theme.chat.inputPanel.inputTextColor
|
||||
self.textFieldNode.textField.keyboardAppearance = self.theme.chat.inputPanel.keyboardColor.keyboardAppearance
|
||||
self.textFieldNode.textField.tintColor = self.theme.list.itemAccentColor
|
||||
}
|
||||
|
||||
private func setColor(_ color: UIColor, updatePicker: Bool = true, ended: Bool = true) {
|
||||
|
@ -179,7 +179,7 @@ public class WallpaperGalleryController: ViewController {
|
||||
switch source {
|
||||
case let .list(wallpapers, central, type):
|
||||
entries = wallpapers.map { .wallpaper($0, nil) }
|
||||
centralEntryIndex = wallpapers.index(of: central)!
|
||||
centralEntryIndex = wallpapers.firstIndex(of: central)!
|
||||
|
||||
if case let .wallpapers(wallpaperOptions) = type, let options = wallpaperOptions {
|
||||
self.initialOptions = options
|
||||
|
@ -267,7 +267,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
}
|
||||
return
|
||||
} else if let offset = self.validOffset, self.arguments.colorPreview && fabs(offset) > 0.0 {
|
||||
} else if let offset = self.validOffset, self.arguments.colorPreview && abs(offset) > 0.0 {
|
||||
return
|
||||
}
|
||||
else {
|
||||
@ -314,7 +314,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
let convertedRepresentations: [ImageRepresentationWithReference] = representations.map({ ImageRepresentationWithReference(representation: $0, reference: .wallpaper(resource: $0.resource)) })
|
||||
signal = wallpaperImage(account: context.account, accountManager: context.sharedContext.accountManager, representations: convertedRepresentations, alwaysShowThumbnailFirst: true, autoFetchFullSize: false)
|
||||
|
||||
if let largestIndex = convertedRepresentations.index(where: { $0.representation == largestSize }) {
|
||||
if let largestIndex = convertedRepresentations.firstIndex(where: { $0.representation == largestSize }) {
|
||||
fetchSignal = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: convertedRepresentations[largestIndex].reference)
|
||||
} else {
|
||||
fetchSignal = .complete()
|
||||
|
@ -13,13 +13,15 @@ final class ShareInputFieldNodeTheme: Equatable {
|
||||
let textColor: UIColor
|
||||
let placeholderColor: UIColor
|
||||
let clearButtonColor: UIColor
|
||||
let accentColor: UIColor
|
||||
let keyboard: PresentationThemeKeyboardColor
|
||||
|
||||
public init(backgroundColor: UIColor, textColor: UIColor, placeholderColor: UIColor, clearButtonColor: UIColor, keyboard: PresentationThemeKeyboardColor) {
|
||||
public init(backgroundColor: UIColor, textColor: UIColor, placeholderColor: UIColor, clearButtonColor: UIColor, accentColor: UIColor, keyboard: PresentationThemeKeyboardColor) {
|
||||
self.backgroundColor = backgroundColor
|
||||
self.textColor = textColor
|
||||
self.placeholderColor = placeholderColor
|
||||
self.clearButtonColor = clearButtonColor
|
||||
self.accentColor = accentColor
|
||||
self.keyboard = keyboard
|
||||
}
|
||||
|
||||
@ -36,6 +38,9 @@ final class ShareInputFieldNodeTheme: Equatable {
|
||||
if lhs.clearButtonColor != rhs.clearButtonColor {
|
||||
return false
|
||||
}
|
||||
if lhs.accentColor != rhs.accentColor {
|
||||
return false
|
||||
}
|
||||
if lhs.keyboard != rhs.keyboard {
|
||||
return false
|
||||
}
|
||||
@ -45,7 +50,7 @@ final class ShareInputFieldNodeTheme: Equatable {
|
||||
|
||||
extension ShareInputFieldNodeTheme {
|
||||
convenience init(presentationTheme theme: PresentationTheme) {
|
||||
self.init(backgroundColor: theme.actionSheet.inputBackgroundColor, textColor: theme.actionSheet.inputTextColor, placeholderColor: theme.actionSheet.inputPlaceholderColor, clearButtonColor: theme.actionSheet.inputClearButtonColor, keyboard: theme.chatList.searchBarKeyboardColor)
|
||||
self.init(backgroundColor: theme.actionSheet.inputBackgroundColor, textColor: theme.actionSheet.inputTextColor, placeholderColor: theme.actionSheet.inputPlaceholderColor, clearButtonColor: theme.actionSheet.inputClearButtonColor, accentColor: theme.actionSheet.controlAccentColor, keyboard: theme.chatList.searchBarKeyboardColor)
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,6 +100,7 @@ final class ShareInputFieldNode: ASDisplayNode, ASEditableTextNodeDelegate {
|
||||
self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
|
||||
self.textInputNode.textContainerInset = UIEdgeInsets(top: self.inputInsets.top, left: 0.0, bottom: self.inputInsets.bottom, right: 0.0)
|
||||
self.textInputNode.keyboardAppearance = theme.keyboard.keyboardAppearance
|
||||
self.textInputNode.tintColor = theme.accentColor
|
||||
|
||||
self.placeholderNode = ASTextNode()
|
||||
self.placeholderNode.isUserInteractionEnabled = false
|
||||
|
@ -287,7 +287,7 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode {
|
||||
var scrollToItem: GridNodeScrollToItem?
|
||||
if let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout {
|
||||
self.ensurePeerVisibleOnLayout = nil
|
||||
if let index = self.entries.index(where: { $0.peer.peerId == ensurePeerVisibleOnLayout }) {
|
||||
if let index = self.entries.firstIndex(where: { $0.peer.peerId == ensurePeerVisibleOnLayout }) {
|
||||
scrollToItem = GridNodeScrollToItem(index: index, position: .visible, transition: transition, directionHint: .up, adjustForSection: false)
|
||||
}
|
||||
}
|
||||
|
@ -42,13 +42,14 @@ final class ShareSearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
||||
self.textInputNode.fixOffset = false
|
||||
let textColor: UIColor = theme.actionSheet.inputTextColor
|
||||
let keyboardAppearance: UIKeyboardAppearance = UIKeyboardAppearance.default
|
||||
textInputNode.textField.font = Font.regular(16.0)
|
||||
textInputNode.textField.textColor = textColor
|
||||
textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(16.0), NSAttributedString.Key.foregroundColor: textColor]
|
||||
textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
|
||||
textInputNode.textField.keyboardAppearance = keyboardAppearance
|
||||
textInputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(16.0), textColor: theme.actionSheet.inputPlaceholderColor)
|
||||
textInputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textInputNode.textField.font = Font.regular(16.0)
|
||||
self.textInputNode.textField.textColor = textColor
|
||||
self.textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(16.0), NSAttributedString.Key.foregroundColor: textColor]
|
||||
self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
|
||||
self.textInputNode.textField.keyboardAppearance = keyboardAppearance
|
||||
self.textInputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(16.0), textColor: theme.actionSheet.inputPlaceholderColor)
|
||||
self.textInputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textInputNode.textField.tintColor = theme.actionSheet.controlAccentColor
|
||||
|
||||
super.init()
|
||||
|
||||
|
@ -71,7 +71,7 @@ private enum ShareSearchRecentEntry: Comparable, Identifiable {
|
||||
return false
|
||||
}
|
||||
case let .peer(lhsIndex, lhsTheme, lhsPeer, lhsAssociatedPeer, lhsPresence, lhsStrings):
|
||||
if case let .peer(rhsIndex, rhsTheme, rhsPeer, rhsAssociatedPeer, rhsPresence, rhsStrings) = rhs, lhsPeer.isEqual(rhsPeer) && arePeersEqual(lhsAssociatedPeer, rhsAssociatedPeer) && lhsIndex == rhsIndex && lhsStrings === rhsStrings && lhsTheme === rhsTheme {
|
||||
if case let .peer(rhsIndex, rhsTheme, rhsPeer, rhsAssociatedPeer, rhsPresence, rhsStrings) = rhs, lhsPeer.isEqual(rhsPeer) && arePeersEqual(lhsAssociatedPeer, rhsAssociatedPeer) && lhsIndex == rhsIndex && lhsStrings === rhsStrings && lhsTheme === rhsTheme && arePeerPresencesEqual(lhsPresence, rhsPresence) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -436,7 +436,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
|
||||
var scrollToItem: GridNodeScrollToItem?
|
||||
if !self.contentGridNode.isHidden, let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout {
|
||||
self.ensurePeerVisibleOnLayout = nil
|
||||
if let index = self.entries.index(where: { $0.peer.peerId == ensurePeerVisibleOnLayout }) {
|
||||
if let index = self.entries.firstIndex(where: { $0.peer.peerId == ensurePeerVisibleOnLayout }) {
|
||||
scrollToItem = GridNodeScrollToItem(index: index, position: .visible, transition: transition, directionHint: .up, adjustForSection: false)
|
||||
}
|
||||
}
|
||||
@ -444,7 +444,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
|
||||
var scrollToRecentItem: GridNodeScrollToItem?
|
||||
if !self.recentGridNode.isHidden, let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout {
|
||||
self.ensurePeerVisibleOnLayout = nil
|
||||
if let index = self.recentEntries.index(where: {
|
||||
if let index = self.recentEntries.firstIndex(where: {
|
||||
switch $0 {
|
||||
case .topPeers:
|
||||
return false
|
||||
|
@ -71,9 +71,12 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
public func updateTheme(_ theme: PresentationTheme) {
|
||||
guard theme !== self.theme else {
|
||||
return
|
||||
}
|
||||
self.theme = theme
|
||||
|
||||
self.buttonBackgroundNode.image = generateStretchableFilledCircleImage(radius: cornerRadius, color: theme.list.itemCheckColors.fillColor)
|
||||
self.buttonBackgroundNode.image = generateStretchableFilledCircleImage(radius: self.buttonCornerRadius, color: theme.list.itemCheckColors.fillColor)
|
||||
self.buttonGlossNode.color = theme.list.itemCheckColors.foregroundColor
|
||||
self.labelNode.attributedText = NSAttributedString(string: self.title ?? "", font: Font.medium(17.0), textColor: theme.list.itemCheckColors.foregroundColor)
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
||||
}
|
||||
|
||||
deinit {
|
||||
stickerFetchedDisposable.dispose()
|
||||
self.stickerFetchedDisposable.dispose()
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
|
@ -29,12 +29,12 @@ public func deleteMessages(transaction: Transaction, mediaBox: MediaBox, ids: [M
|
||||
transaction.deleteMessages(ids)
|
||||
}
|
||||
|
||||
public func clearHistory(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId) {
|
||||
public func clearHistory(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, namespaces: MessageIdNamespaces) {
|
||||
if peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
transaction.withAllMessages(peerId: peerId, { message in
|
||||
removeMessageMedia(message: message, mediaBox: mediaBox)
|
||||
return true
|
||||
})
|
||||
}
|
||||
transaction.clearHistory(peerId)
|
||||
transaction.clearHistory(peerId, namespaces: namespaces)
|
||||
}
|
||||
|
@ -90,16 +90,18 @@ public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId, type: In
|
||||
return postbox.transaction { transaction -> Void in
|
||||
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup || peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
cloudChatAddClearHistoryOperation(transaction: transaction, peerId: peerId, explicitTopMessageId: nil, type: CloudChatClearHistoryType(type))
|
||||
if type != .scheduledMessages {
|
||||
if type == .scheduledMessages {
|
||||
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .just(Namespaces.Message.allScheduled))
|
||||
} else {
|
||||
var topIndex: MessageIndex?
|
||||
if let topMessageId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud), let topMessage = transaction.getMessage(topMessageId) {
|
||||
topIndex = topMessage.index
|
||||
}
|
||||
|
||||
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId)
|
||||
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .not(Namespaces.Message.allScheduled))
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, let migrationReference = cachedData.migrationReference {
|
||||
cloudChatAddClearHistoryOperation(transaction: transaction, peerId: migrationReference.maxMessageId.peerId, explicitTopMessageId: MessageId(peerId: migrationReference.maxMessageId.peerId, namespace: migrationReference.maxMessageId.namespace, id: migrationReference.maxMessageId.id + 1), type: CloudChatClearHistoryType(type))
|
||||
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: migrationReference.maxMessageId.peerId)
|
||||
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: migrationReference.maxMessageId.peerId, namespaces: .all)
|
||||
}
|
||||
if let topIndex = topIndex {
|
||||
if peerId.namespace == Namespaces.Peer.CloudUser {
|
||||
@ -110,7 +112,7 @@ public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId, type: In
|
||||
}
|
||||
}
|
||||
} else if peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId)
|
||||
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .all)
|
||||
|
||||
if let state = transaction.getPeerChatState(peerId) as? SecretChatState {
|
||||
var layer: SecretChatLayer?
|
||||
|
@ -309,7 +309,7 @@ private func removeChat(transaction: Transaction, postbox: Postbox, network: Net
|
||||
|> then(deleteUser)
|
||||
|> then(reportSignal)
|
||||
|> then(postbox.transaction { transaction -> Void in
|
||||
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id)
|
||||
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id, namespaces: .all)
|
||||
})
|
||||
} else if peer.id.namespace == Namespaces.Peer.CloudUser {
|
||||
if let inputPeer = apiInputPeer(peer) {
|
||||
@ -328,7 +328,7 @@ private func removeChat(transaction: Transaction, postbox: Postbox, network: Net
|
||||
return requestClearHistory(postbox: postbox, network: network, stateManager: stateManager, inputPeer: inputPeer, maxId: operation.topMessageId?.id ?? Int32.max - 1, justClear: false, type: operation.deleteGloballyIfPossible ? .forEveryone : .forLocalPeer)
|
||||
|> then(reportSignal)
|
||||
|> then(postbox.transaction { transaction -> Void in
|
||||
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id)
|
||||
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id, namespaces: .not(Namespaces.Message.allScheduled))
|
||||
})
|
||||
} else {
|
||||
return .complete()
|
||||
|
@ -282,7 +282,7 @@ func processSecretChatIncomingDecryptedOperations(mediaBox: MediaBox, transactio
|
||||
deleteMessages(transaction: transaction, mediaBox: mediaBox, ids: filteredMessageIds)
|
||||
}
|
||||
case .clearHistory:
|
||||
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId)
|
||||
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all)
|
||||
case let .markMessagesContentAsConsumed(globallyUniqueIds):
|
||||
var messageIds: [MessageId] = []
|
||||
for id in globallyUniqueIds {
|
||||
|
@ -49,17 +49,17 @@ public func removePeerChat(account: Account, transaction: Transaction, mediaBox:
|
||||
}
|
||||
}
|
||||
}
|
||||
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId)
|
||||
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all)
|
||||
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
|
||||
transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, itemId: RecentPeerItemId(peerId).rawValue)
|
||||
} else {
|
||||
cloudChatAddRemoveChatOperation(transaction: transaction, peerId: peerId, reportChatSpam: reportChatSpam, deleteGloballyIfPossible: deleteGloballyIfPossible)
|
||||
if peerId.namespace == Namespaces.Peer.CloudUser {
|
||||
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
|
||||
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId)
|
||||
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all)
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
|
||||
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId)
|
||||
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all)
|
||||
} else {
|
||||
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
|
||||
}
|
||||
|
@ -106,7 +106,11 @@ private func requestEditMessageInternal(account: Account, messageId: MessageId,
|
||||
case _ as TelegramMediaImage, _ as TelegramMediaFile:
|
||||
break
|
||||
default:
|
||||
return (nil, nil, SimpleDictionary())
|
||||
if let _ = scheduleTime {
|
||||
break
|
||||
} else {
|
||||
return (nil, nil, SimpleDictionary())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ public func searchStickers(account: Account, query: String, scope: SearchSticker
|
||||
|
||||
var searchQuery: ItemCollectionSearchQuery = .exact(ValueBoxKey(query))
|
||||
if query == "\u{2764}" {
|
||||
searchQuery = .matching([ValueBoxKey("\u{2764}"), ValueBoxKey("\u{2764}\u{fe0f}")])
|
||||
searchQuery = .any([ValueBoxKey("\u{2764}"), ValueBoxKey("\u{2764}\u{FE0F}")])
|
||||
}
|
||||
|
||||
var installedItems: [FoundStickerItem] = []
|
||||
|
@ -3,50 +3,50 @@ import UIKit
|
||||
import Display
|
||||
|
||||
public extension TabBarControllerTheme {
|
||||
convenience public init(rootControllerTheme: PresentationTheme) {
|
||||
convenience init(rootControllerTheme: PresentationTheme) {
|
||||
let theme = rootControllerTheme.rootController.tabBar
|
||||
self.init(backgroundColor: rootControllerTheme.list.plainBackgroundColor, tabBarBackgroundColor: theme.backgroundColor, tabBarSeparatorColor: theme.separatorColor, tabBarTextColor: theme.textColor, tabBarSelectedTextColor: theme.selectedIconColor, tabBarBadgeBackgroundColor: theme.badgeBackgroundColor, tabBarBadgeStrokeColor: theme.badgeStrokeColor, tabBarBadgeTextColor: theme.badgeTextColor)
|
||||
}
|
||||
}
|
||||
|
||||
public extension NavigationBarTheme {
|
||||
convenience public init(rootControllerTheme: PresentationTheme) {
|
||||
convenience init(rootControllerTheme: PresentationTheme) {
|
||||
let theme = rootControllerTheme.rootController.navigationBar
|
||||
self.init(buttonColor: theme.buttonColor, disabledButtonColor: theme.disabledButtonColor, primaryTextColor: theme.primaryTextColor, backgroundColor: theme.backgroundColor, separatorColor: theme.separatorColor, badgeBackgroundColor: theme.badgeBackgroundColor, badgeStrokeColor: theme.badgeStrokeColor, badgeTextColor: theme.badgeTextColor)
|
||||
}
|
||||
}
|
||||
|
||||
public extension NavigationBarStrings {
|
||||
convenience public init(presentationStrings: PresentationStrings) {
|
||||
convenience init(presentationStrings: PresentationStrings) {
|
||||
self.init(back: presentationStrings.Common_Back, close: presentationStrings.Common_Close)
|
||||
}
|
||||
}
|
||||
|
||||
public extension NavigationBarPresentationData {
|
||||
convenience public init(presentationData: PresentationData) {
|
||||
convenience init(presentationData: PresentationData) {
|
||||
self.init(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme), strings: NavigationBarStrings(presentationStrings: presentationData.strings))
|
||||
}
|
||||
|
||||
convenience public init(presentationTheme: PresentationTheme, presentationStrings: PresentationStrings) {
|
||||
convenience init(presentationTheme: PresentationTheme, presentationStrings: PresentationStrings) {
|
||||
self.init(theme: NavigationBarTheme(rootControllerTheme: presentationTheme), strings: NavigationBarStrings(presentationStrings: presentationStrings))
|
||||
}
|
||||
}
|
||||
|
||||
public extension ActionSheetControllerTheme {
|
||||
convenience public init(presentationTheme: PresentationTheme) {
|
||||
convenience init(presentationTheme: PresentationTheme) {
|
||||
let actionSheet = presentationTheme.actionSheet
|
||||
self.init(dimColor: actionSheet.dimColor, backgroundType: actionSheet.backgroundType == .light ? .light : .dark, itemBackgroundColor: actionSheet.itemBackgroundColor, itemHighlightedBackgroundColor: actionSheet.itemHighlightedBackgroundColor, standardActionTextColor: actionSheet.standardActionTextColor, destructiveActionTextColor: actionSheet.destructiveActionTextColor, disabledActionTextColor: actionSheet.disabledActionTextColor, primaryTextColor: actionSheet.primaryTextColor, secondaryTextColor: actionSheet.secondaryTextColor, controlAccentColor: actionSheet.controlAccentColor, controlColor: presentationTheme.list.disclosureArrowColor, switchFrameColor: presentationTheme.list.itemSwitchColors.frameColor, switchContentColor: presentationTheme.list.itemSwitchColors.contentColor, switchHandleColor: presentationTheme.list.itemSwitchColors.handleColor)
|
||||
}
|
||||
}
|
||||
|
||||
public extension ActionSheetController {
|
||||
convenience public init(presentationTheme: PresentationTheme) {
|
||||
convenience init(presentationTheme: PresentationTheme) {
|
||||
self.init(theme: ActionSheetControllerTheme(presentationTheme: presentationTheme))
|
||||
}
|
||||
}
|
||||
|
||||
public extension AlertControllerTheme {
|
||||
convenience public init(presentationTheme: PresentationTheme) {
|
||||
convenience init(presentationTheme: PresentationTheme) {
|
||||
let actionSheet = presentationTheme.actionSheet
|
||||
self.init(backgroundType: actionSheet.backgroundType == .light ? .light : .dark, backgroundColor: actionSheet.itemBackgroundColor, separatorColor: actionSheet.itemHighlightedBackgroundColor, highlightedItemColor: actionSheet.itemHighlightedBackgroundColor, primaryColor: actionSheet.primaryTextColor, secondaryColor: actionSheet.secondaryTextColor, accentColor: actionSheet.controlAccentColor, destructiveColor: actionSheet.destructiveActionTextColor, disabledColor: actionSheet.disabledActionTextColor)
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
|
||||
outgoingBubbleFillColor = accentColor
|
||||
|
||||
let hsv = accentColor.hsv
|
||||
accentColor = UIColor(hue: hsv.0, saturation: hsv.1 * 1.1, brightness: min(hsv.2, 0.77), alpha: 1.0)
|
||||
accentColor = UIColor(hue: hsv.0, saturation: hsv.1 * 1.1, brightness: min(hsv.2, 0.7), alpha: 1.0)
|
||||
} else {
|
||||
outgoingPrimaryTextColor = .white
|
||||
outgoingSecondaryTextColor = UIColor(rgb: 0xffffff, alpha: 0.65)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,6 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import TelegramPresentationData
|
||||
|
||||
private func generateStatusCheckImage(theme: PresentationTheme, single: Bool) -> UIImage? {
|
||||
return generateImage(CGSize(width: single ? 13.0 : 18.0, height: 13.0), rotatedContext: { size, context in
|
||||
|
@ -1,7 +1,6 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import TelegramPresentationData
|
||||
|
||||
private func generateArrowImage(_ theme: PresentationTheme) -> UIImage? {
|
||||
return generateImage(CGSize(width: 7.0, height: 13.0), rotatedContext: { size, context in
|
||||
|
@ -1,7 +1,6 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import TelegramPresentationData
|
||||
|
||||
private func generateShareButtonImage(theme: PresentationTheme) -> UIImage? {
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat List/NavigationShare"), color: theme.rootController.navigationBar.accentTextColor)
|
||||
|
@ -40,5 +40,7 @@ func presentationStringsPluralizationForm(_ lc: UInt32, _ value: Int32) -> Plura
|
||||
return .many
|
||||
case .other:
|
||||
return .other
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +107,8 @@ private final class PhoneAndCountryNode: ASDisplayNode {
|
||||
self.phoneInputNode.numberField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.countryCodeField.textField.textColor = theme.list.itemPrimaryTextColor
|
||||
self.phoneInputNode.numberField.textField.textColor = theme.list.itemPrimaryTextColor
|
||||
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor
|
||||
self.phoneInputNode.numberField.textField.tintColor = theme.list.itemAccentColor
|
||||
|
||||
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor
|
||||
self.phoneInputNode.numberField.textField.tintColor = theme.list.itemAccentColor
|
||||
|
@ -108,6 +108,8 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
self.firstNameField.textField.textContentType = .givenName
|
||||
}
|
||||
self.firstNameField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.firstNameField.textField.tintColor = theme.list.itemAccentColor
|
||||
|
||||
self.lastNameField = TextFieldNode()
|
||||
self.lastNameField.textField.font = Font.regular(20.0)
|
||||
@ -120,6 +122,8 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
self.lastNameField.textField.textContentType = .familyName
|
||||
}
|
||||
self.lastNameField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.lastNameField.textField.tintColor = theme.list.itemAccentColor
|
||||
|
||||
self.currentPhotoNode = ASImageNode()
|
||||
self.currentPhotoNode.isUserInteractionEnabled = false
|
||||
|
@ -543,6 +543,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
reactionItems.append(ReactionContextItem(value: value, text: text, path: path))
|
||||
}
|
||||
}
|
||||
if Namespaces.Message.allScheduled.contains(message.id.namespace) {
|
||||
reactionItems = []
|
||||
}
|
||||
let controller = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: ChatMessageContextControllerContentSource(chatNode: strongSelf.chatDisplayNode, message: message), items: actions, reactionItems: reactionItems, recognizer: recognizer)
|
||||
strongSelf.currentContextController = controller
|
||||
controller.reactionSelected = { [weak controller] value in
|
||||
@ -1395,6 +1398,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction else {
|
||||
return
|
||||
}
|
||||
guard !strongSelf.presentationInterfaceState.isScheduledMessages else {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.ScheduledMessages_PollUnavailable, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
return
|
||||
}
|
||||
if controllerInteraction.pollActionState.pollMessageIdsInProgress[id] == nil {
|
||||
controllerInteraction.pollActionState.pollMessageIdsInProgress[id] = opaqueIdentifier
|
||||
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
|
||||
@ -2804,7 +2811,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
} else {
|
||||
text = "\(count) messages selected"
|
||||
}
|
||||
UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: text)
|
||||
UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: text)
|
||||
}
|
||||
}
|
||||
}, deleteSelectedMessages: { [weak self] in
|
||||
@ -4547,6 +4554,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.chatDisplayNode.updateChatPresentationInterfaceState(updatedChatPresentationInterfaceState, transition: transition, interactive: interactive)
|
||||
}
|
||||
|
||||
if let selectionState = self.presentationInterfaceState.interfaceState.selectionState, !selectionState.selectedIds.isEmpty {
|
||||
self.chatTitleView?.titleContent = .custom(self.presentationData.strings.Conversation_SelectedMessages(Int32(selectionState.selectedIds.count)))
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if let button = leftNavigationButtonForChatInterfaceState(updatedChatPresentationInterfaceState, strings: updatedChatPresentationInterfaceState.strings, currentButton: self.leftNavigationButton, target: self, selector: #selector(self.leftNavigationButtonAction)) {
|
||||
if self.leftNavigationButton != button {
|
||||
var animated = transition.isAnimated
|
||||
@ -4586,7 +4599,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
switch updatedChatPresentationInterfaceState.mode {
|
||||
case .standard:
|
||||
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
||||
self.deferScreenEdgeGestures = []
|
||||
self.deferScreenEdgeGestures = []
|
||||
case .overlay:
|
||||
self.statusBar.statusBarStyle = .Hide
|
||||
self.deferScreenEdgeGestures = [.top]
|
||||
@ -7383,9 +7396,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let peer = peer as? TelegramUser {
|
||||
let recipientHandle = INPersonHandle(value: "tg\(peerId.id)", type: .unknown)
|
||||
let recipient = INPerson(personHandle: recipientHandle, nameComponents: nil, displayName: peer.displayTitle, image: nil, contactIdentifier: nil, customIdentifier: "tg\(peerId.id)")
|
||||
|
||||
let intent = INSendMessageIntent(recipients: [recipient], content: nil, groupName: nil, serviceName: nil, sender: nil)
|
||||
|
||||
let interaction = INInteraction(intent: intent, response: nil)
|
||||
interaction.direction = .outgoing
|
||||
interaction.donate { error in
|
||||
|
@ -258,7 +258,8 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte
|
||||
accessoryItems.append(.messageAutoremoveTimeout(peer.messageAutoremoveTimeout))
|
||||
}
|
||||
}
|
||||
if chatPresentationInterfaceState.interfaceState.composeInputState.inputText.length == 0 {
|
||||
|
||||
if chatPresentationInterfaceState.interfaceState.composeInputState.inputText.length == 0 && chatPresentationInterfaceState.interfaceState.forwardMessageIds == nil {
|
||||
if chatPresentationInterfaceState.hasScheduledMessages {
|
||||
accessoryItems.append(.scheduledMessages)
|
||||
}
|
||||
|
@ -169,13 +169,15 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
||||
}
|
||||
|
||||
var displayBotStartPanel = false
|
||||
if let _ = chatPresentationInterfaceState.botStartPayload {
|
||||
if let user = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil {
|
||||
displayBotStartPanel = true
|
||||
}
|
||||
} else if let chatHistoryState = chatPresentationInterfaceState.chatHistoryState, case .loaded(true) = chatHistoryState {
|
||||
if let user = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil {
|
||||
displayBotStartPanel = true
|
||||
if !chatPresentationInterfaceState.isScheduledMessages {
|
||||
if let _ = chatPresentationInterfaceState.botStartPayload {
|
||||
if let user = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil {
|
||||
displayBotStartPanel = true
|
||||
}
|
||||
} else if let chatHistoryState = chatPresentationInterfaceState.chatHistoryState, case .loaded(true) = chatHistoryState {
|
||||
if let user = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil {
|
||||
displayBotStartPanel = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,7 +400,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
|
||||
let reactionRecognizer = ReactionSwipeGestureRecognizer(target: nil, action: nil)
|
||||
self.reactionRecognizer = reactionRecognizer
|
||||
reactionRecognizer.availableReactions = { [weak self] in
|
||||
guard let strongSelf = self, let item = strongSelf.item else {
|
||||
guard let strongSelf = self, let item = strongSelf.item, !Namespaces.Message.allScheduled.contains(item.message.id.namespace) else {
|
||||
return []
|
||||
}
|
||||
if strongSelf.selectionNode != nil {
|
||||
|
@ -773,6 +773,9 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
canVote = true
|
||||
}
|
||||
}
|
||||
if Namespaces.Message.allScheduled.contains(item.message.id.namespace) {
|
||||
canVote = true
|
||||
}
|
||||
|
||||
return (boundingSize.width, { boundingWidth in
|
||||
var resultSize = CGSize(width: max(boundingSize.width, boundingWidth), height: boundingSize.height)
|
||||
|
@ -24,6 +24,8 @@ final class ChatScheduleTimeController: ViewController {
|
||||
private let currentTime: Int32?
|
||||
private let completion: (Int32) -> Void
|
||||
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
init(context: AccountContext, mode: ChatScheduleTimeControllerMode, currentTime: Int32? = nil, completion: @escaping (Int32) -> Void) {
|
||||
self.context = context
|
||||
self.mode = mode
|
||||
@ -32,6 +34,13 @@ final class ChatScheduleTimeController: ViewController {
|
||||
|
||||
super.init(navigationBarPresentationData: nil)
|
||||
|
||||
self.presentationDataDisposable = (context.sharedContext.presentationData
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerNode.updatePresentationData(presentationData)
|
||||
}
|
||||
})
|
||||
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
}
|
||||
|
||||
@ -39,6 +48,10 @@ final class ChatScheduleTimeController: ViewController {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.presentationDataDisposable?.dispose()
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = ChatScheduleTimeControllerNode(context: self.context, mode: self.mode, currentTime: self.currentTime)
|
||||
self.controllerNode.completion = { [weak self] time in
|
||||
|
@ -20,7 +20,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
private let contentContainerNode: ASDisplayNode
|
||||
private let contentBackgroundNode: ASImageNode
|
||||
private let titleNode: ASTextNode
|
||||
private let separatorNode: ASDisplayNode
|
||||
private let cancelButton: HighlightableButtonNode
|
||||
private let doneButton: SolidRoundedButtonNode
|
||||
|
||||
@ -46,8 +45,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
self.dimNode = ASDisplayNode()
|
||||
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
|
||||
|
||||
let roundedBackground = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)
|
||||
|
||||
self.contentContainerNode = ASDisplayNode()
|
||||
self.contentContainerNode.isOpaque = false
|
||||
self.contentContainerNode.clipsToBounds = true
|
||||
@ -55,7 +52,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
self.contentBackgroundNode = ASImageNode()
|
||||
self.contentBackgroundNode.displaysAsynchronously = false
|
||||
self.contentBackgroundNode.displayWithoutProcessing = true
|
||||
self.contentBackgroundNode.image = roundedBackground
|
||||
self.contentBackgroundNode.image = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)
|
||||
|
||||
let title: String
|
||||
switch mode {
|
||||
@ -68,9 +65,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.bold(17.0), textColor: self.presentationData.theme.actionSheet.primaryTextColor)
|
||||
|
||||
self.separatorNode = ASDisplayNode()
|
||||
//self.separatorNode.backgroundColor = self.theme.controlColor
|
||||
|
||||
self.cancelButton = HighlightableButtonNode()
|
||||
self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
|
||||
|
||||
@ -107,7 +101,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
self.pickerView.timeZone = TimeZone.current
|
||||
self.pickerView.minuteInterval = 1
|
||||
self.pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor")
|
||||
|
||||
self.contentContainerNode.view.addSubview(self.pickerView)
|
||||
self.pickerView.addTarget(self, action: #selector(self.datePickerUpdated), for: .valueChanged)
|
||||
|
||||
@ -116,6 +109,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
if let strongSelf = self {
|
||||
if strongSelf.pickerView.date < Date() {
|
||||
strongSelf.updateMinimumDate()
|
||||
strongSelf.updateButtonTitle()
|
||||
strongSelf.pickerView.layer.addShakeAnimation()
|
||||
} else {
|
||||
strongSelf.doneButton.isUserInteractionEnabled = false
|
||||
@ -128,6 +122,17 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
self.updateButtonTitle()
|
||||
}
|
||||
|
||||
func updatePresentationData(_ presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
|
||||
self.contentBackgroundNode.image = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.titleNode.attributedText?.string ?? "", font: Font.bold(17.0), textColor: self.presentationData.theme.actionSheet.primaryTextColor)
|
||||
self.pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor")
|
||||
|
||||
self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
|
||||
self.doneButton.updateTheme(self.presentationData.theme)
|
||||
}
|
||||
|
||||
private func updateMinimumDate(currentTime: Int32? = nil) {
|
||||
let timeZone = TimeZone(secondsFromGMT: 0)!
|
||||
var calendar = Calendar(identifier: .gregorian)
|
||||
@ -137,16 +142,19 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
components.second = 0
|
||||
let minute = (components.minute ?? 0) % 5
|
||||
|
||||
let next1MinDate = calendar.date(byAdding: .minute, value: 1, to: calendar.date(from: components)!)
|
||||
let next5MinDate = calendar.date(byAdding: .minute, value: 5 - minute, to: calendar.date(from: components)!)
|
||||
|
||||
if let date = calendar.date(byAdding: .day, value: 365, to: currentDate) {
|
||||
self.pickerView.maximumDate = date
|
||||
}
|
||||
|
||||
if let date = calendar.date(byAdding: .minute, value: 5 - minute, to: calendar.date(from: components)!) {
|
||||
self.pickerView.minimumDate = date
|
||||
if let currentTime = currentTime {
|
||||
if let next1MinDate = next1MinDate, let next5MinDate = next5MinDate {
|
||||
self.pickerView.minimumDate = next1MinDate
|
||||
if let currentTime = currentTime, Double(currentTime) > currentDate.timeIntervalSince1970 {
|
||||
self.pickerView.date = Date(timeIntervalSince1970: Double(currentTime))
|
||||
} else {
|
||||
self.pickerView.date = date
|
||||
self.pickerView.date = next5MinDate
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -300,6 +308,5 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
self.pickerView.frame = CGRect(origin: CGPoint(x: 0.0, y: 54.0), size: CGSize(width: contentFrame.width, height: pickerHeight))
|
||||
|
||||
transition.updateFrame(node: self.contentContainerNode, frame: contentContainerFrame)
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: titleHeight), size: CGSize(width: contentContainerFrame.size.width, height: UIScreenPixel)))
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
|
||||
self.textInputNode.autocapitalizationType = .none
|
||||
self.textInputNode.returnKeyType = .done
|
||||
self.textInputNode.autocorrectionType = .no
|
||||
self.textInputNode.tintColor = theme.actionSheet.controlAccentColor
|
||||
|
||||
self.placeholderNode = ASTextNode()
|
||||
self.placeholderNode.isUserInteractionEnabled = false
|
||||
@ -75,9 +76,10 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
|
||||
func updateTheme(_ theme: PresentationTheme) {
|
||||
self.theme = theme
|
||||
|
||||
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 33.0, color: theme.actionSheet.inputHollowBackgroundColor, strokeColor: theme.actionSheet.inputBorderColor, strokeWidth: 1.0)
|
||||
self.textInputNode.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 33.0, color: self.theme.actionSheet.inputHollowBackgroundColor, strokeColor: self.theme.actionSheet.inputBorderColor, strokeWidth: 1.0)
|
||||
self.textInputNode.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.placeholderNode.attributedText = NSAttributedString(string: self.placeholderNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
|
||||
self.textInputNode.tintColor = self.theme.actionSheet.controlAccentColor
|
||||
}
|
||||
|
||||
func updateLayout(width: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
|
@ -16,6 +16,7 @@ import ChatTitleActivityNode
|
||||
enum ChatTitleContent {
|
||||
case peer(peerView: PeerView, onlineMemberCount: Int32?, isScheduledMessages: Bool)
|
||||
case group([Peer])
|
||||
case custom(String)
|
||||
}
|
||||
|
||||
private final class ChatTitleNetworkStatusNode: ASDisplayNode {
|
||||
@ -182,7 +183,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
switch titleContent {
|
||||
case let .peer(peerView, _, isScheduledMessages):
|
||||
if isScheduledMessages {
|
||||
if let peer = peerViewMainPeer(peerView), peerView.peerId == self.account.peerId {
|
||||
if peerView.peerId == self.account.peerId {
|
||||
string = NSAttributedString(string: self.strings.ScheduledMessages_RemindersTitle, font: Font.medium(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
|
||||
} else {
|
||||
string = NSAttributedString(string: self.strings.ScheduledMessages_Title, font: Font.medium(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
|
||||
@ -212,6 +213,8 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
}
|
||||
case .group:
|
||||
string = NSAttributedString(string: "Feed", font: Font.medium(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
|
||||
case let .custom(text):
|
||||
string = NSAttributedString(string: text, font: Font.medium(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
|
||||
}
|
||||
|
||||
if let string = string, self.titleNode.attributedText == nil || !self.titleNode.attributedText!.isEqual(to: string) {
|
||||
@ -263,7 +266,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
inputActivitiesAllowed = false
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,7 +432,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
}
|
||||
}
|
||||
}
|
||||
case .group:
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
self.contactListNode = ContactListNode(context: context, presentation: .single(.natural(options: options, includeChatList: includeChatList)), filters: filters, selectionState: ContactListNodeGroupSelectionState())
|
||||
self.tokenListNode = EditableTokenListNode(theme: EditableTokenListNodeTheme(backgroundColor: self.presentationData.theme.rootController.navigationBar.backgroundColor, separatorColor: self.presentationData.theme.rootController.navigationBar.separatorColor, placeholderTextColor: self.presentationData.theme.list.itemPlaceholderTextColor, primaryTextColor: self.presentationData.theme.list.itemPrimaryTextColor, selectedTextColor: self.presentationData.theme.list.itemAccentColor, keyboardColor: self.presentationData.theme.chatList.searchBarKeyboardColor), placeholder: placeholder)
|
||||
self.tokenListNode = EditableTokenListNode(theme: EditableTokenListNodeTheme(backgroundColor: self.presentationData.theme.rootController.navigationBar.backgroundColor, separatorColor: self.presentationData.theme.rootController.navigationBar.separatorColor, placeholderTextColor: self.presentationData.theme.list.itemPlaceholderTextColor, primaryTextColor: self.presentationData.theme.list.itemPrimaryTextColor, selectedTextColor: self.presentationData.theme.list.itemAccentColor, accentColor: self.presentationData.theme.list.itemAccentColor, keyboardColor: self.presentationData.theme.chatList.searchBarKeyboardColor), placeholder: placeholder)
|
||||
|
||||
super.init()
|
||||
|
||||
|
@ -32,14 +32,16 @@ final class EditableTokenListNodeTheme {
|
||||
let placeholderTextColor: UIColor
|
||||
let primaryTextColor: UIColor
|
||||
let selectedTextColor: UIColor
|
||||
let accentColor: UIColor
|
||||
let keyboardColor: PresentationThemeKeyboardColor
|
||||
|
||||
init(backgroundColor: UIColor, separatorColor: UIColor, placeholderTextColor: UIColor, primaryTextColor: UIColor, selectedTextColor: UIColor, keyboardColor: PresentationThemeKeyboardColor) {
|
||||
init(backgroundColor: UIColor, separatorColor: UIColor, placeholderTextColor: UIColor, primaryTextColor: UIColor, selectedTextColor: UIColor, accentColor: UIColor, keyboardColor: PresentationThemeKeyboardColor) {
|
||||
self.backgroundColor = backgroundColor
|
||||
self.separatorColor = separatorColor
|
||||
self.placeholderTextColor = placeholderTextColor
|
||||
self.primaryTextColor = primaryTextColor
|
||||
self.selectedTextColor = selectedTextColor
|
||||
self.accentColor = accentColor
|
||||
self.keyboardColor = keyboardColor
|
||||
}
|
||||
}
|
||||
@ -123,12 +125,8 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate {
|
||||
self.textFieldNode.textField.textColor = theme.primaryTextColor
|
||||
self.textFieldNode.textField.autocorrectionType = .no
|
||||
self.textFieldNode.textField.returnKeyType = .done
|
||||
switch theme.keyboardColor {
|
||||
case .light:
|
||||
self.textFieldNode.textField.keyboardAppearance = .default
|
||||
case .dark:
|
||||
self.textFieldNode.textField.keyboardAppearance = .dark
|
||||
}
|
||||
self.textFieldNode.textField.keyboardAppearance = theme.keyboardColor.keyboardAppearance
|
||||
self.textFieldNode.textField.tintColor = theme.accentColor
|
||||
|
||||
self.caretIndicatorNode = CaretIndicatorNode()
|
||||
self.caretIndicatorNode.isLayerBacked = true
|
||||
|
@ -263,13 +263,8 @@ class PaneSearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
||||
self.iconNode.image = generateLoupeIcon(color: theme.chat.inputMediaPanel.stickersSearchControlColor)
|
||||
self.clearButton.setImage(generateClearIcon(color: theme.chat.inputMediaPanel.stickersSearchControlColor), for: [])
|
||||
self.cancelButton.setAttributedTitle(NSAttributedString(string: strings.Common_Cancel, font: Font.regular(17.0), textColor: theme.chat.inputPanel.panelControlAccentColor), for: [])
|
||||
|
||||
switch theme.chatList.searchBarKeyboardColor {
|
||||
case .light:
|
||||
self.textField.keyboardAppearance = .default
|
||||
case .dark:
|
||||
self.textField.keyboardAppearance = .dark
|
||||
}
|
||||
self.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textField.tintColor = theme.list.itemAccentColor
|
||||
|
||||
if let (boundingSize, leftInset, rightInset) = self.validLayout {
|
||||
self.updateLayout(boundingSize: boundingSize, leftInset: leftInset, rightInset: rightInset, transition: .immediate)
|
||||
|
Binary file not shown.
@ -11,7 +11,7 @@ import PhotoResources
|
||||
import LocalMediaResources
|
||||
|
||||
private func wallpaperDatas(account: Account, accountManager: AccountManager, fileReference: FileMediaReference? = nil, representations: [ImageRepresentationWithReference], alwaysShowThumbnailFirst: Bool = false, thumbnail: Bool = false, autoFetchFullSize: Bool = false, synchronousLoad: Bool = false) -> Signal<(Data?, Data?, Bool), NoError> {
|
||||
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.index(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.index(where: { $0.representation == largestRepresentation }) {
|
||||
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
|
||||
|
||||
let maybeFullSize: Signal<MediaResourceData, NoError>
|
||||
if thumbnail, let file = fileReference?.media {
|
||||
@ -284,7 +284,7 @@ public enum PatternWallpaperDrawMode {
|
||||
}
|
||||
|
||||
private func patternWallpaperDatas(account: Account, accountManager: AccountManager, representations: [ImageRepresentationWithReference], mode: PatternWallpaperDrawMode, autoFetchFullSize: Bool = false) -> Signal<(Data?, Data?, Bool), NoError> {
|
||||
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.index(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.index(where: { $0.representation == largestRepresentation }) {
|
||||
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
|
||||
|
||||
let size: CGSize?
|
||||
switch mode {
|
||||
|
@ -379,6 +379,8 @@ final class WatchMediaHandler: WatchRequestHandler {
|
||||
round = true
|
||||
case .large:
|
||||
targetSize = CGSize(width: 150, height: 150);
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
|
||||
return SSignal { subscriber in
|
||||
|
@ -618,20 +618,15 @@ class WebSearchControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
private func dequeueTransition() {
|
||||
if let (transition, firstTime) = self.enqueuedTransitions.first {
|
||||
if let (transition, _) = self.enqueuedTransitions.first {
|
||||
self.enqueuedTransitions.remove(at: 0)
|
||||
|
||||
let completion: (GridNodeDisplayedItemRange) -> Void = { [weak self] visibleRange in
|
||||
if let strongSelf = self {
|
||||
}
|
||||
}
|
||||
|
||||
if let state = self.webSearchInterfaceState.state {
|
||||
self.recentQueriesNode.isHidden = !state.query.isEmpty
|
||||
}
|
||||
|
||||
self.hasMore = transition.hasMore
|
||||
self.gridNode.transaction(GridNodeTransaction(deleteItems: transition.deleteItems, insertItems: transition.insertItems, updateItems: transition.updateItems, scrollToItem: nil, updateLayout: nil, itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil, synchronousLoads: true), completion: completion)
|
||||
self.gridNode.transaction(GridNodeTransaction(deleteItems: transition.deleteItems, insertItems: transition.insertItems, updateItems: transition.updateItems, scrollToItem: nil, updateLayout: nil, itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil, synchronousLoads: true), completion: { _ in })
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user