diff --git a/TelegramUI.xcodeproj/project.pbxproj b/TelegramUI.xcodeproj/project.pbxproj index 8bc1c8f998..dbabc1e5ee 100644 --- a/TelegramUI.xcodeproj/project.pbxproj +++ b/TelegramUI.xcodeproj/project.pbxproj @@ -7,9 +7,20 @@ objects = { /* Begin PBXBuildFile section */ + 09310D1D213BC5DE0020033A /* anim_read.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D14213BC5DE0020033A /* anim_read.json */; }; + 09310D1E213BC5DE0020033A /* anim_pin.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D15213BC5DE0020033A /* anim_pin.json */; }; + 09310D1F213BC5DE0020033A /* anim_unmute.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D16213BC5DE0020033A /* anim_unmute.json */; }; + 09310D20213BC5DE0020033A /* anim_unpin.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D17213BC5DE0020033A /* anim_unpin.json */; }; + 09310D21213BC5DE0020033A /* anim_unread.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D18213BC5DE0020033A /* anim_unread.json */; }; + 09310D22213BC5DE0020033A /* anim_delete.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D19213BC5DE0020033A /* anim_delete.json */; }; + 09310D23213BC5DE0020033A /* anim_ungroup.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D1A213BC5DE0020033A /* anim_ungroup.json */; }; + 09310D24213BC5DE0020033A /* anim_group.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D1B213BC5DE0020033A /* anim_group.json */; }; + 09310D25213BC5DE0020033A /* anim_mute.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D1C213BC5DE0020033A /* anim_mute.json */; }; + 09310D29213BD8810020033A /* Lottie.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09310D28213BD8810020033A /* Lottie.framework */; }; 0941A9A0210B057200EBE194 /* OpenInActionSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0941A99F210B057200EBE194 /* OpenInActionSheetController.swift */; }; 0941A9A4210B0E2E00EBE194 /* OpenInAppIconResources.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0941A9A3210B0E2E00EBE194 /* OpenInAppIconResources.swift */; }; 0941A9A6210B822D00EBE194 /* OpenInOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0941A9A5210B822D00EBE194 /* OpenInOptions.swift */; }; + 094981C62138D73B00A10660 /* Vision.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 094981C52138D73B00A10660 /* Vision.framework */; }; 09797873210633CD0077D77F /* InstantPageSettingsButtonItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09797872210633CD0077D77F /* InstantPageSettingsButtonItemNode.swift */; }; 0979787C210642CB0077D77F /* WebEmbedPlayerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0979787B210642CB0077D77F /* WebEmbedPlayerNode.swift */; }; 0979787E210646C00077D77F /* YoutubeEmbedImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0979787D210646C00077D77F /* YoutubeEmbedImplementation.swift */; }; @@ -176,7 +187,6 @@ D056CD781FF2A6EE00880D28 /* ChatMessageSwipeToReplyNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D056CD771FF2A6EE00880D28 /* ChatMessageSwipeToReplyNode.swift */; }; D056CD7A1FF3CC2A00880D28 /* ListMessagePlaybackOverlayNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D056CD791FF3CC2A00880D28 /* ListMessagePlaybackOverlayNode.swift */; }; D056CD7C1FF3E92C00880D28 /* DirectionalPanGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D056CD7B1FF3E92C00880D28 /* DirectionalPanGestureRecognizer.swift */; }; - D057C5452004235000990762 /* mute.json in Resources */ = {isa = PBXBuildFile; fileRef = D057C5422004226C00990762 /* mute.json */; }; D0642EFC1F3E1E7B00792790 /* ChatHistoryNavigationButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0642EFB1F3E1E7B00792790 /* ChatHistoryNavigationButtons.swift */; }; D064EF871F69A06F00AC0398 /* MessageContentKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = D064EF861F69A06F00AC0398 /* MessageContentKind.swift */; }; D067B4A5211C911C00796039 /* LegacyChannelIntroController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D067B4A4211C911C00796039 /* LegacyChannelIntroController.swift */; }; @@ -1005,9 +1015,21 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 09310D14213BC5DE0020033A /* anim_read.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_read.json; sourceTree = ""; }; + 09310D15213BC5DE0020033A /* anim_pin.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_pin.json; sourceTree = ""; }; + 09310D16213BC5DE0020033A /* anim_unmute.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_unmute.json; sourceTree = ""; }; + 09310D17213BC5DE0020033A /* anim_unpin.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_unpin.json; sourceTree = ""; }; + 09310D18213BC5DE0020033A /* anim_unread.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_unread.json; sourceTree = ""; }; + 09310D19213BC5DE0020033A /* anim_delete.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_delete.json; sourceTree = ""; }; + 09310D1A213BC5DE0020033A /* anim_ungroup.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_ungroup.json; sourceTree = ""; }; + 09310D1B213BC5DE0020033A /* anim_group.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_group.json; sourceTree = ""; }; + 09310D1C213BC5DE0020033A /* anim_mute.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_mute.json; sourceTree = ""; }; + 09310D26213BD84E0020033A /* Lottie.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Lottie.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 09310D28213BD8810020033A /* Lottie.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Lottie.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 0941A99F210B057200EBE194 /* OpenInActionSheetController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInActionSheetController.swift; sourceTree = ""; }; 0941A9A3210B0E2E00EBE194 /* OpenInAppIconResources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInAppIconResources.swift; sourceTree = ""; }; 0941A9A5210B822D00EBE194 /* OpenInOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInOptions.swift; sourceTree = ""; }; + 094981C52138D73B00A10660 /* Vision.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Vision.framework; path = System/Library/Frameworks/Vision.framework; sourceTree = SDKROOT; }; 09797872210633CD0077D77F /* InstantPageSettingsButtonItemNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstantPageSettingsButtonItemNode.swift; sourceTree = ""; }; 0979787B210642CB0077D77F /* WebEmbedPlayerNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebEmbedPlayerNode.swift; sourceTree = ""; }; 0979787D210646C00077D77F /* YoutubeEmbedImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YoutubeEmbedImplementation.swift; sourceTree = ""; }; @@ -1402,7 +1424,6 @@ D0575AFB1EA104A6006F2541 /* PeerAvatarImageGalleryItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerAvatarImageGalleryItem.swift; sourceTree = ""; }; D057C52B2004202900990762 /* libLottie.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libLottie.a; sourceTree = BUILT_PRODUCTS_DIR; }; D057C5412004215B00990762 /* Lottie.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Lottie.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D057C5422004226C00990762 /* mute.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = mute.json; path = TelegramUI/Resources/mute.json; sourceTree = ""; }; D05811931DD5F9380057C769 /* TelegramApplicationContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TelegramApplicationContext.swift; sourceTree = ""; }; D058E0CE1E8AD57300A442DE /* VideoPlayerProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerProxy.swift; sourceTree = ""; }; D05A32DB1E6EFCC2002760B4 /* NumericFormat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumericFormat.swift; sourceTree = ""; }; @@ -2094,8 +2115,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 09310D29213BD8810020033A /* Lottie.framework in Frameworks */, D00ACA4B20222C280045D427 /* libtgvoip.framework in Frameworks */, D07BCBFE1F2B792300ED97AA /* LegacyComponents.framework in Frameworks */, + 094981C62138D73B00A10660 /* Vision.framework in Frameworks */, D053B4371F1A9CA000E2D58A /* WebKit.framework in Frameworks */, D09E63B21F11289A003444CD /* PassKit.framework in Frameworks */, D09E63B01F1010FE003444CD /* Contacts.framework in Frameworks */, @@ -2130,6 +2153,23 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 09310D13213BC5DE0020033A /* Animations */ = { + isa = PBXGroup; + children = ( + 09310D14213BC5DE0020033A /* anim_read.json */, + 09310D15213BC5DE0020033A /* anim_pin.json */, + 09310D16213BC5DE0020033A /* anim_unmute.json */, + 09310D17213BC5DE0020033A /* anim_unpin.json */, + 09310D18213BC5DE0020033A /* anim_unread.json */, + 09310D19213BC5DE0020033A /* anim_delete.json */, + 09310D1A213BC5DE0020033A /* anim_ungroup.json */, + 09310D1B213BC5DE0020033A /* anim_group.json */, + 09310D1C213BC5DE0020033A /* anim_mute.json */, + ); + name = Animations; + path = TelegramUI/Resources/Animations; + sourceTree = ""; + }; 0941A99E210B053300EBE194 /* Open In */ = { isa = PBXGroup; children = ( @@ -2469,7 +2509,7 @@ D0471B521EFD8EBC0074D609 /* Resources */ = { isa = PBXGroup; children = ( - D057C5422004226C00990762 /* mute.json */, + 09310D13213BC5DE0020033A /* Animations */, D0C12A1B1F33964900B3F66D /* ChatWallpaperBuiltin0.jpg */, D0E9BA681F056F4C00F079A4 /* Stripe */, D0E9B9E91F00853C00F079A4 /* PhoneCountries.txt */, @@ -2959,6 +2999,9 @@ D08D45281D5E340200A7428A /* Frameworks */ = { isa = PBXGroup; children = ( + 09310D28213BD8810020033A /* Lottie.framework */, + 09310D26213BD84E0020033A /* Lottie.framework */, + 094981C52138D73B00A10660 /* Vision.framework */, D00ACA4C20222C280045D427 /* libtgvoip.framework */, D057C5412004215B00990762 /* Lottie.framework */, D057C52B2004202900990762 /* libLottie.a */, @@ -4560,7 +4603,6 @@ D0E9BA981F056F4C00F079A4 /* stp_card_applepay_template@3x.png in Resources */, D0E9BAA51F056F4C00F079A4 /* stp_card_form_applepay@2x.png in Resources */, D0E9BAB81F056F4C00F079A4 /* stp_card_visa_template@3x.png in Resources */, - D057C5452004235000990762 /* mute.json in Resources */, D0E9BA9B1F056F4C00F079A4 /* stp_card_cvc_amex@2x.png in Resources */, D0E9BAB61F056F4C00F079A4 /* stp_card_visa@3x.png in Resources */, D0E9BAA61F056F4C00F079A4 /* stp_card_form_applepay@3x.png in Resources */, @@ -4571,6 +4613,15 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 09310D24213BC5DE0020033A /* anim_group.json in Resources */, + 09310D1E213BC5DE0020033A /* anim_pin.json in Resources */, + 09310D23213BC5DE0020033A /* anim_ungroup.json in Resources */, + 09310D20213BC5DE0020033A /* anim_unpin.json in Resources */, + 09310D1F213BC5DE0020033A /* anim_unmute.json in Resources */, + 09310D21213BC5DE0020033A /* anim_unread.json in Resources */, + 09310D1D213BC5DE0020033A /* anim_read.json in Resources */, + 09310D22213BC5DE0020033A /* anim_delete.json in Resources */, + 09310D25213BC5DE0020033A /* anim_mute.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/TelegramUI/AuthorizationSequenceSplashController.swift b/TelegramUI/AuthorizationSequenceSplashController.swift index 937aa933af..f2ac9cbe75 100644 --- a/TelegramUI/AuthorizationSequenceSplashController.swift +++ b/TelegramUI/AuthorizationSequenceSplashController.swift @@ -59,7 +59,7 @@ final class AuthorizationSequenceSplashController: ViewController { }) }) - self.controller = RMIntroViewController(backroundColor: theme.backgroundColor, primaryColor: theme.primaryColor, accentColor: theme.accentColor, regularDotColor: theme.disclosureControlColor, highlightedDotColor: theme.accentColor, suggestedLocalizationSignal: localizationSignal) + self.controller = RMIntroViewController(backroundColor: theme.backgroundColor, primaryColor: theme.primaryColor, buttonColor: theme.startButtonColor, accentColor: theme.accentColor, regularDotColor: theme.disclosureControlColor, highlightedDotColor: theme.primaryColor, suggestedLocalizationSignal: localizationSignal) super.init(navigationBarPresentationData: nil) diff --git a/TelegramUI/AuthorizationTheme.swift b/TelegramUI/AuthorizationTheme.swift index 062f91d97d..b8d86d3f79 100644 --- a/TelegramUI/AuthorizationTheme.swift +++ b/TelegramUI/AuthorizationTheme.swift @@ -16,6 +16,7 @@ public final class AuthorizationTheme { let primaryColor: UIColor let separatorColor: UIColor let itemHighlightedBackgroundColor: UIColor + let startButtonColor: UIColor let accentColor: UIColor let destructiveColor: UIColor let disclosureControlColor: UIColor @@ -23,7 +24,7 @@ public final class AuthorizationTheme { let alertBackgroundColor: UIColor let listBackgroundColor: UIColor - init(statusBarStyle: StatusBarStyle, navigationBarBackgroundColor: UIColor, navigationBarTextColor: UIColor, navigationBarSeparatorColor: UIColor, searchBarBackgroundColor: UIColor, searchBarFillColor: UIColor, searchBarPlaceholderColor: UIColor, searchBarTextColor: UIColor, keyboardAppearance: UIKeyboardAppearance, backgroundColor: UIColor, primaryColor: UIColor, separatorColor: UIColor, itemHighlightedBackgroundColor: UIColor, accentColor: UIColor, destructiveColor: UIColor, disclosureControlColor: UIColor, textPlaceholderColor: UIColor, alertBackgroundColor: UIColor, listBackgroundColor: UIColor) { + init(statusBarStyle: StatusBarStyle, navigationBarBackgroundColor: UIColor, navigationBarTextColor: UIColor, navigationBarSeparatorColor: UIColor, searchBarBackgroundColor: UIColor, searchBarFillColor: UIColor, searchBarPlaceholderColor: UIColor, searchBarTextColor: UIColor, keyboardAppearance: UIKeyboardAppearance, backgroundColor: UIColor, primaryColor: UIColor, separatorColor: UIColor, itemHighlightedBackgroundColor: UIColor, startButtonColor: UIColor, accentColor: UIColor, destructiveColor: UIColor, disclosureControlColor: UIColor, textPlaceholderColor: UIColor, alertBackgroundColor: UIColor, listBackgroundColor: UIColor) { self.statusBarStyle = statusBarStyle self.navigationBarBackgroundColor = navigationBarBackgroundColor self.navigationBarTextColor = navigationBarTextColor @@ -37,6 +38,7 @@ public final class AuthorizationTheme { self.primaryColor = primaryColor self.separatorColor = separatorColor self.itemHighlightedBackgroundColor = itemHighlightedBackgroundColor + self.startButtonColor = startButtonColor self.accentColor = accentColor self.destructiveColor = destructiveColor self.disclosureControlColor = disclosureControlColor @@ -60,6 +62,7 @@ let defaultLightAuthorizationTheme = AuthorizationTheme( primaryColor: .black, separatorColor: UIColor(red: 0.6953125, green: 0.6953125, blue: 0.6953125, alpha: 1.0), itemHighlightedBackgroundColor: UIColor(rgb: 0xd9d9d9), + startButtonColor: UIColor(rgb: 0x2ca5e0), accentColor: UIColor(rgb: 0x007ee5), destructiveColor: UIColor(rgb: 0xff3b30), disclosureControlColor: UIColor(rgb: 0xbab9be), @@ -82,6 +85,7 @@ let defaultAuthorizationTheme = AuthorizationTheme( primaryColor: .white, separatorColor: UIColor(rgb: 0x252525), itemHighlightedBackgroundColor: UIColor(rgb: 0x1b1b1b), + startButtonColor: .white, accentColor: .white, destructiveColor: UIColor(rgb: 0xFF736B), disclosureControlColor: UIColor(rgb: 0x717171), diff --git a/TelegramUI/BotCheckoutControllerNode.swift b/TelegramUI/BotCheckoutControllerNode.swift index 98c332d4ab..a9f0ffe426 100644 --- a/TelegramUI/BotCheckoutControllerNode.swift +++ b/TelegramUI/BotCheckoutControllerNode.swift @@ -825,7 +825,11 @@ final class BotCheckoutControllerNode: ItemListControllerNode, let alertText: String if requiresBiometrics { - alertText = strongSelf.presentationData.strings.Checkout_SavePasswordTimeoutAndTouchId(durationString).0 + if let biometricAuthentication = LocalAuth.biometricAuthentication, case .faceId = biometricAuthentication { + alertText = strongSelf.presentationData.strings.Checkout_SavePasswordTimeoutAndFaceId(durationString).0 + } else { + alertText = strongSelf.presentationData.strings.Checkout_SavePasswordTimeoutAndTouchId(durationString).0 + } } else { alertText = strongSelf.presentationData.strings.Checkout_SavePasswordTimeout(durationString).0 } diff --git a/TelegramUI/BotCheckoutInfoController.swift b/TelegramUI/BotCheckoutInfoController.swift index bbc079bdac..b640d47216 100644 --- a/TelegramUI/BotCheckoutInfoController.swift +++ b/TelegramUI/BotCheckoutInfoController.swift @@ -150,6 +150,7 @@ final class BotCheckoutInfoController: ViewController { } override open func dismiss(completion: (() -> Void)? = nil) { + self.view.endEditing(true) self.controllerNode.animateOut(completion: completion) } } diff --git a/TelegramUI/BotCheckoutInfoControllerNode.swift b/TelegramUI/BotCheckoutInfoControllerNode.swift index 30df199673..12923594d9 100644 --- a/TelegramUI/BotCheckoutInfoControllerNode.swift +++ b/TelegramUI/BotCheckoutInfoControllerNode.swift @@ -25,12 +25,12 @@ private final class BotCheckoutInfoAddressItems { } init(strings: PresentationStrings, openCountrySelection: @escaping () -> Void) { - self.address1 = BotPaymentFieldItemNode(title: strings.CheckoutInfo_ShippingInfoAddress1, placeholder: strings.CheckoutInfo_ShippingInfoAddress1Placeholder) - self.address2 = BotPaymentFieldItemNode(title: strings.CheckoutInfo_ShippingInfoAddress2, placeholder: strings.CheckoutInfo_ShippingInfoAddress2Placeholder) - self.city = BotPaymentFieldItemNode(title: strings.CheckoutInfo_ShippingInfoCity, placeholder: strings.CheckoutInfo_ShippingInfoCityPlaceholder) - self.state = BotPaymentFieldItemNode(title: strings.CheckoutInfo_ShippingInfoState, placeholder: strings.CheckoutInfo_ShippingInfoStatePlaceholder) + self.address1 = BotPaymentFieldItemNode(title: strings.CheckoutInfo_ShippingInfoAddress1, placeholder: strings.CheckoutInfo_ShippingInfoAddress1Placeholder, contentType: .address) + self.address2 = BotPaymentFieldItemNode(title: strings.CheckoutInfo_ShippingInfoAddress2, placeholder: strings.CheckoutInfo_ShippingInfoAddress2Placeholder, contentType: .address) + self.city = BotPaymentFieldItemNode(title: strings.CheckoutInfo_ShippingInfoCity, placeholder: strings.CheckoutInfo_ShippingInfoCityPlaceholder, contentType: .address) + self.state = BotPaymentFieldItemNode(title: strings.CheckoutInfo_ShippingInfoState, placeholder: strings.CheckoutInfo_ShippingInfoStatePlaceholder, contentType: .address) self.country = BotPaymentDisclosureItemNode(title: strings.CheckoutInfo_ShippingInfoCountry, placeholder: strings.CheckoutInfo_ShippingInfoCountryPlaceholder, text: "") - self.postcode = BotPaymentFieldItemNode(title: strings.CheckoutInfo_ShippingInfoPostcode, placeholder: strings.CheckoutInfo_ShippingInfoPostcodePlaceholder) + self.postcode = BotPaymentFieldItemNode(title: strings.CheckoutInfo_ShippingInfoPostcode, placeholder: strings.CheckoutInfo_ShippingInfoPostcodePlaceholder, contentType: .address) self.country.action = { openCountrySelection() diff --git a/TelegramUI/BotCheckoutNativeCardEntryControllerNode.swift b/TelegramUI/BotCheckoutNativeCardEntryControllerNode.swift index f008a36ab6..e2a7a5ef20 100644 --- a/TelegramUI/BotCheckoutNativeCardEntryControllerNode.swift +++ b/TelegramUI/BotCheckoutNativeCardEntryControllerNode.swift @@ -123,7 +123,7 @@ final class BotCheckoutNativeCardEntryControllerNode: ViewControllerTracingNode, self.countryItem = nil } if additionalFields.contains(.zipCode) { - let zipCodeItem = BotPaymentFieldItemNode(title: "", placeholder: strings.Checkout_NewCard_PostcodePlaceholder) + let zipCodeItem = BotPaymentFieldItemNode(title: "", placeholder: strings.Checkout_NewCard_PostcodePlaceholder, contentType: .address) self.zipCodeItem = zipCodeItem sectionItems.append(zipCodeItem) } else { @@ -152,6 +152,9 @@ final class BotCheckoutNativeCardEntryControllerNode: ViewControllerTracingNode, self.backgroundColor = self.theme.list.blocksBackgroundColor self.scrollNode.backgroundColor = nil self.scrollNode.isOpaque = false + if #available(iOSApplicationExtension 11.0, *) { + self.scrollNode.view.contentInsetAdjustmentBehavior = .never + } self.scrollNode.view.alwaysBounceVertical = true self.scrollNode.view.showsVerticalScrollIndicator = false self.scrollNode.view.showsHorizontalScrollIndicator = false @@ -199,6 +202,10 @@ final class BotCheckoutNativeCardEntryControllerNode: ViewControllerTracingNode, } } + cardItem.completed = { [weak self] in + self?.cardholderItem?.activateInput() + } + self.updateDone() } diff --git a/TelegramUI/BotPaymentCardInputItemNode.swift b/TelegramUI/BotPaymentCardInputItemNode.swift index 2ac57d471d..2b8a0226a2 100644 --- a/TelegramUI/BotPaymentCardInputItemNode.swift +++ b/TelegramUI/BotPaymentCardInputItemNode.swift @@ -17,6 +17,7 @@ final class BotPaymentCardInputItemNode: BotPaymentItemNode, STPPaymentCardTextF private var theme: PresentationTheme? var updated: ((BotPaymentCardInputData?) -> Void)? + var completed: (() -> Void)? init() { self.cardField = STPPaymentCardTextField() @@ -51,6 +52,10 @@ final class BotPaymentCardInputItemNode: BotPaymentItemNode, STPPaymentCardTextF func paymentCardTextFieldDidChange(_ textField: STPPaymentCardTextField) { if textField.isValid, let number = textField.cardParams.number, let code = textField.cardParams.cvc { self.updated?(BotPaymentCardInputData(number: number, code: code, year: textField.cardParams.expYear, month: textField.cardParams.expMonth)) + + if code.count == 3 { + self.completed?() + } } else { self.updated?(nil) } diff --git a/TelegramUI/BotPaymentFieldItemNode.swift b/TelegramUI/BotPaymentFieldItemNode.swift index 1afe6716a3..ab08e3d089 100644 --- a/TelegramUI/BotPaymentFieldItemNode.swift +++ b/TelegramUI/BotPaymentFieldItemNode.swift @@ -8,6 +8,8 @@ enum BotPaymentFieldContentType { case generic case creditCardholderName case phoneNumber + case email + case address } final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate { @@ -45,13 +47,18 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate { switch contentType { case .generic: break - case .creditCardholderName: + case .creditCardholderName, .address: self.textField.textField.autocorrectionType = .no case .phoneNumber: self.textField.textField.keyboardType = .numberPad if #available(iOSApplicationExtension 10.0, *) { self.textField.textField.textContentType = .telephoneNumber } + case .email: + self.textField.textField.keyboardType = .emailAddress + if #available(iOSApplicationExtension 10.0, *) { + self.textField.textField.textContentType = .emailAddress + } } super.init(needsBackground: true) diff --git a/TelegramUI/BotReceiptControllerNode.swift b/TelegramUI/BotReceiptControllerNode.swift index 38d8eca532..ec17ea07ae 100644 --- a/TelegramUI/BotReceiptControllerNode.swift +++ b/TelegramUI/BotReceiptControllerNode.swift @@ -298,7 +298,7 @@ final class BotReceiptControllerNode: ItemListControllerNode { updatedInsets.bottom += BotCheckoutActionButton.diameter + 20.0 super.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, intrinsicInsets: updatedInsets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, standardInputHeight: layout.standardInputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging), navigationBarHeight: navigationBarHeight, transition: transition) - let actionButtonFrame = CGRect(origin: CGPoint(x: 10.0, y: layout.size.height - 10.0 - BotCheckoutActionButton.diameter), size: CGSize(width: layout.size.width - 20.0, height: BotCheckoutActionButton.diameter)) + let actionButtonFrame = CGRect(origin: CGPoint(x: 10.0, y: layout.size.height - 10.0 - BotCheckoutActionButton.diameter - layout.intrinsicInsets.bottom), size: CGSize(width: layout.size.width - 20.0, height: BotCheckoutActionButton.diameter)) transition.updateFrame(node: self.actionButton, frame: actionButtonFrame) self.actionButton.updateLayout(size: actionButtonFrame.size, transition: transition) } diff --git a/TelegramUI/ChannelInfoController.swift b/TelegramUI/ChannelInfoController.swift index 9e04b0fff5..908ea2e4dd 100644 --- a/TelegramUI/ChannelInfoController.swift +++ b/TelegramUI/ChannelInfoController.swift @@ -434,7 +434,7 @@ private func channelInfoEntries(account: Account, presentationData: Presentation entries.append(.admins(theme: presentationData.theme, text: presentationData.strings.Channel_Info_Management, value: "\(adminCount)")) } if let memberCount = cachedChannelData.participantsSummary.memberCount { - entries.append(.members(theme: presentationData.theme, text: presentationData.strings.Channel_Info_Members, value: "\(memberCount)")) + entries.append(.members(theme: presentationData.theme, text: presentationData.strings.Channel_Info_Subscribers, value: "\(memberCount)")) } } } diff --git a/TelegramUI/ChannelMembersController.swift b/TelegramUI/ChannelMembersController.swift index bc0adce059..e8dc3695dc 100644 --- a/TelegramUI/ChannelMembersController.swift +++ b/TelegramUI/ChannelMembersController.swift @@ -436,7 +436,7 @@ public func channelMembersController(account: Account, peerId: PeerId) -> ViewCo let previous = previousPeers previousPeers = peers - let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Channel_Members_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) + let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Channel_Subscribers_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) let listState = ItemListNodeState(entries: ChannelMembersControllerEntries(account: account, presentationData: presentationData, view: view, state: state, participants: peers), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: previous != nil && peers != nil && previous!.count >= peers!.count) return (controllerState, (listState, arguments)) diff --git a/TelegramUI/ChatButtonKeyboardInputNode.swift b/TelegramUI/ChatButtonKeyboardInputNode.swift index 5a9a7a4398..f72af8225b 100644 --- a/TelegramUI/ChatButtonKeyboardInputNode.swift +++ b/TelegramUI/ChatButtonKeyboardInputNode.swift @@ -137,11 +137,12 @@ final class ChatButtonKeyboardInputNode: ChatInputNode { } if markup.flags.contains(.fit) { - panelHeight = min(panelHeight, rowsHeight + bottomInset) + panelHeight = min(panelHeight + bottomInset, rowsHeight + bottomInset) } transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight))) self.scrollNode.view.contentSize = CGSize(width: width, height: rowsHeight) + self.scrollNode.view.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: bottomInset, right: 0) return (panelHeight, 0.0) } else { diff --git a/TelegramUI/ChatController.swift b/TelegramUI/ChatController.swift index dc153c8ee9..946ec37eec 100644 --- a/TelegramUI/ChatController.swift +++ b/TelegramUI/ChatController.swift @@ -617,23 +617,43 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin self?.presentInGlobalOverlay(controller, with: arguments) }, callPeer: { [weak self] peerId in if let strongSelf = self { - let callResult = strongSelf.account.telegramApplicationContext.callManager?.requestCall(peerId: peerId, endCurrentIfAny: false) - if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult { - if currentPeerId == peerId { - strongSelf.account.telegramApplicationContext.navigateToCurrentCall?() - } else { - let presentationData = strongSelf.presentationData - let _ = (account.postbox.transaction { transaction -> (Peer?, Peer?) in - return (transaction.getPeer(peerId), transaction.getPeer(currentPeerId)) - } |> deliverOnMainQueue).start(next: { peer, current in - if let strongSelf = self, let peer = peer, let current = current { - strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: presentationData.strings.Call_CallInProgressTitle, text: presentationData.strings.Call_CallInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: { - let _ = account.telegramApplicationContext.callManager?.requestCall(peerId: peerId, endCurrentIfAny: true) - })]), in: .window(.root)) - } - }) + func getUserPeer(postbox: Postbox, peerId: PeerId) -> Signal { + return postbox.transaction { transaction -> Peer? in + guard let peer = transaction.getPeer(peerId) else { + return nil + } + if let peer = peer as? TelegramSecretChat { + return transaction.getPeer(peer.regularPeerId) + } else { + return peer + } } } + + let _ = (getUserPeer(postbox: strongSelf.account.postbox, peerId: peerId) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + let callResult = account.telegramApplicationContext.callManager?.requestCall(peerId: peer.id, endCurrentIfAny: false) + if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult { + if currentPeerId == peer.id { + account.telegramApplicationContext.navigateToCurrentCall?() + } else { + let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } + let _ = (account.postbox.transaction { transaction -> (Peer?, Peer?) in + return (transaction.getPeer(peer.id), transaction.getPeer(currentPeerId)) + } |> deliverOnMainQueue).start(next: { peer, current in + if let peer = peer, let current = current { + strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: presentationData.strings.Call_CallInProgressTitle, text: presentationData.strings.Call_CallInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: { + let _ = account.telegramApplicationContext.callManager?.requestCall(peerId: peer.id, endCurrentIfAny: true) + })]), in: .window(.root)) + } + }) + } + } + }) } }, longTap: { [weak self] action in if let strongSelf = self { @@ -3095,7 +3115,7 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin }) }, openCamera: { cameraView, menuController in if let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer { - presentedLegacyCamera(account: strongSelf.account, peer: peer, cameraView: cameraView, menuController: menuController, parentController: strongSelf, editingMedia: editMediaOptions != nil, saveCapturedPhotos: settings.storeEditedPhotos, sendMessagesWithSignals: { signals in + presentedLegacyCamera(account: strongSelf.account, peer: peer, cameraView: cameraView, menuController: menuController, parentController: strongSelf, editingMedia: editMediaOptions != nil, saveCapturedPhotos: settings.storeEditedPhotos, mediaGrouping: true, sendMessagesWithSignals: { signals in if editMediaOptions != nil { self?.editMessageMediaWithLegacySignals(signals!) } else { @@ -4256,7 +4276,9 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin if let applicationContext = self.account.applicationContext as? TelegramApplicationContext { let actionSheet = OpenInActionSheetController(postbox: self.account.postbox, applicationContext: applicationContext, theme: self.presentationData.theme, strings: self.presentationData.strings, item: .url(url), openUrl: { [weak self] url in if let strongSelf = self, let applicationContext = strongSelf.account.applicationContext as? TelegramApplicationContext, let navigationController = strongSelf.navigationController as? NavigationController { - openExternalUrl(account: strongSelf.account, url: url, presentationData: strongSelf.presentationData, applicationContext: applicationContext, navigationController: navigationController) + openExternalUrl(account: strongSelf.account, url: url, presentationData: strongSelf.presentationData, applicationContext: applicationContext, navigationController: navigationController, dismissInput: { + self?.chatDisplayNode.dismissInput() + }) } }) self.chatDisplayNode.dismissInput() diff --git a/TelegramUI/ChatInfoTitlePanelNode.swift b/TelegramUI/ChatInfoTitlePanelNode.swift index 42ecb450a4..93fde5a7e6 100644 --- a/TelegramUI/ChatInfoTitlePanelNode.swift +++ b/TelegramUI/ChatInfoTitlePanelNode.swift @@ -68,6 +68,12 @@ private func peerButtons(_ peer: Peer, isMuted: Bool) -> [ChatInfoTitleButton] { if peer.botInfo == nil { buttons.append(.call) } + + buttons.append(.info) + return buttons + } else if let _ = peer as? TelegramSecretChat { + var buttons: [ChatInfoTitleButton] = [.search, muteAction] + buttons.append(.call) buttons.append(.info) return buttons } else if let channel = peer as? TelegramChannel { diff --git a/TelegramUI/ChatInterfaceInputContexts.swift b/TelegramUI/ChatInterfaceInputContexts.swift index cc7febec99..8b6f9b954e 100644 --- a/TelegramUI/ChatInterfaceInputContexts.swift +++ b/TelegramUI/ChatInterfaceInputContexts.swift @@ -213,6 +213,22 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte break loop } } + + var accessoryItems: [ChatTextInputAccessoryItem] = [] + if let peer = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramSecretChat { + var extendedSearchLayout = false + loop: for (_, result) in chatPresentationInterfaceState.inputQueryResults { + if case let .contextRequestResult(peer, _) = result, peer != nil { + extendedSearchLayout = true + break loop + } + } + + if !extendedSearchLayout { + accessoryItems.append(.messageAutoremoveTimeout(peer.messageAutoremoveTimeout)) + } + } + switch chatPresentationInterfaceState.inputMode { case .media: if contextPlaceholder == nil && chatPresentationInterfaceState.interfaceState.editMessage == nil && chatPresentationInterfaceState.interfaceState.composeInputState.inputText.length == 0, case .media(.gif, _) = chatPresentationInterfaceState.inputMode { @@ -220,7 +236,8 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte contextPlaceholder = NSAttributedString(string: "@gif", font: Font.regular(baseFontSize), textColor: chatPresentationInterfaceState.theme.chat.inputPanel.inputPlaceholderColor) } - return ChatTextInputPanelState(accessoryItems: [.keyboard], contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) + accessoryItems.append(.keyboard) + return ChatTextInputPanelState(accessoryItems: accessoryItems, contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) case .inputButtons: return ChatTextInputPanelState(accessoryItems: [.keyboard], contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) case .none, .text: @@ -238,7 +255,7 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte } if !extendedSearchLayout { - accessoryItems.append(.messageAutoremoveTimeout(peer.messageAutoremoveTimeout)) + accessoryItems.append(.messageAutoremoveTimeout(peer.messageAutoremoveTimeout)) } } if chatPresentationInterfaceState.interfaceState.composeInputState.inputText.length == 0 { diff --git a/TelegramUI/ChatListItemStrings.swift b/TelegramUI/ChatListItemStrings.swift index bcc63bb674..e991b54554 100644 --- a/TelegramUI/ChatListItemStrings.swift +++ b/TelegramUI/ChatListItemStrings.swift @@ -15,101 +15,123 @@ public func chatListItemStrings(strings: PresentationStrings, message: Message?, } messageText = message.text - if message.text.isEmpty { - for media in message.media { - switch media { - case _ as TelegramMediaImage: - if message.text.isEmpty { - messageText = strings.Message_Photo + + for media in message.media { + switch media { + case _ as TelegramMediaImage: + if message.text.isEmpty { + messageText = strings.Message_Photo + } else if #available(iOSApplicationExtension 9.0, *) { + messageText = "🖼 \(messageText)" + } + case let fileMedia as TelegramMediaFile: + if message.text.isEmpty { + if let fileName = fileMedia.fileName { + messageText = fileName + } else { + messageText = strings.Message_File } - case let fileMedia as TelegramMediaFile: - if message.text.isEmpty { - if let fileName = fileMedia.fileName { - messageText = fileName + } + var isAnimated = false + inner: for attribute in fileMedia.attributes { + switch attribute { + case .Animated: + isAnimated = true + break inner + case let .Audio(isVoice, _, title, performer, _): + if isVoice { + messageText = strings.Message_Audio + break inner } else { - messageText = strings.Message_File + let descriptionString: String + if let title = title, let performer = performer, !title.isEmpty, !performer.isEmpty { + descriptionString = title + " — " + performer + } else if let title = title, !title.isEmpty { + descriptionString = title + } else if let performer = performer, !performer.isEmpty { + descriptionString = performer + } else if let fileName = fileMedia.fileName { + descriptionString = fileName + } else { + descriptionString = strings.Message_Audio + } + messageText = descriptionString + break inner } - var isAnimated = false - inner: for attribute in fileMedia.attributes { - switch attribute { - case .Animated: - isAnimated = true - break inner - case let .Audio(isVoice, _, title, performer, _): - if isVoice { - messageText = strings.Message_Audio - break inner - } else { - let descriptionString: String - if let title = title, let performer = performer, !title.isEmpty, !performer.isEmpty { - descriptionString = title + " — " + performer - } else if let title = title, !title.isEmpty { - descriptionString = title - } else if let performer = performer, !performer.isEmpty { - descriptionString = performer - } else if let fileName = fileMedia.fileName { - descriptionString = fileName - } else { - descriptionString = strings.Message_Audio - } - messageText = descriptionString - break inner - } - case let .Sticker(displayText, _, _): - if displayText.isEmpty { - messageText = strings.Message_Sticker - break inner - } else { - messageText = displayText + " " + strings.Message_Sticker - break inner - } - case let .Video(_, _, flags): - if flags.contains(.instantRoundVideo) { - messageText = strings.Message_VideoMessage - } else { - messageText = strings.Message_Video - } - default: - break + case let .Sticker(displayText, _, _): + if displayText.isEmpty { + messageText = strings.Message_Sticker + break inner + } else { + messageText = displayText + " " + strings.Message_Sticker + break inner + } + case let .Video(_, _, flags): + if flags.contains(.instantRoundVideo) { + messageText = strings.Message_VideoMessage + } else { + if message.text.isEmpty { + messageText = strings.Message_Video + } else if #available(iOSApplicationExtension 9.0, *) { + messageText = "📹 \(messageText)" } } - if isAnimated { - messageText = strings.Message_Animation + default: + if !message.text.isEmpty { + messageText = "📎 \(messageText)" + } + break + } + } + if isAnimated { + messageText = strings.Message_Animation + } + case let location as TelegramMediaMap: + if location.liveBroadcastingTimeout != nil { + messageText = strings.Message_LiveLocation + } else { + messageText = strings.Message_Location + } + case _ as TelegramMediaContact: + messageText = strings.Message_Contact + case let game as TelegramMediaGame: + messageText = "🎮 \(game.title)" + case let invoice as TelegramMediaInvoice: + messageText = invoice.title + case let action as TelegramMediaAction: + hideAuthor = true + switch action.action { + case let .phoneCall(_, discardReason, _): + let incoming = message.flags.contains(.Incoming) + if let discardReason = discardReason { + switch discardReason { + case .busy, .disconnect: + messageText = strings.Notification_CallCanceled + case .missed: + messageText = incoming ? strings.Notification_CallMissed : strings.Notification_CallCanceled + case .hangup: + break } } - case let location as TelegramMediaMap: - if location.liveBroadcastingTimeout != nil { - messageText = strings.Message_LiveLocation - } else { - messageText = strings.Message_Location - } - case _ as TelegramMediaContact: - messageText = strings.Message_Contact - case let game as TelegramMediaGame: - messageText = "🎮 \(game.title)" - case let invoice as TelegramMediaInvoice: - messageText = invoice.title - case let action as TelegramMediaAction: - hideAuthor = true - switch action.action { - case .phoneCall: - if message.flags.contains(.Incoming) { + + if messageText.isEmpty { + if incoming { messageText = strings.Notification_CallIncoming } else { messageText = strings.Notification_CallOutgoing } - default: - if let text = plainServiceMessageString(strings: strings, message: message, accountPeerId: accountPeerId) { - messageText = text - } } - case _ as TelegramMediaExpiredContent: + default: if let text = plainServiceMessageString(strings: strings, message: message, accountPeerId: accountPeerId) { messageText = text } - default: - break } + case _ as TelegramMediaExpiredContent: + if let text = plainServiceMessageString(strings: strings, message: message, accountPeerId: accountPeerId) { + messageText = text + } + default: + break } } } else { diff --git a/TelegramUI/ChatListSearchContainerNode.swift b/TelegramUI/ChatListSearchContainerNode.swift index 8c5bca6947..93ead88518 100644 --- a/TelegramUI/ChatListSearchContainerNode.swift +++ b/TelegramUI/ChatListSearchContainerNode.swift @@ -146,7 +146,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable { if let user = primaryPeer as? TelegramUser { if let _ = user.botInfo { status = .custom(strings.Bot_GenericBotStatus) - } else if let presence = peer.presence { + } else if user.id != account.peerId, let presence = peer.presence { status = .presence(presence, timeFormat) } else { status = .none @@ -162,7 +162,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable { } } else { if let count = peer.subpeerSummary?.count { - status = .custom(strings.Conversation_StatusMembers(Int32(count))) + status = .custom(strings.Conversation_StatusSubscribers(Int32(count))) } else { status = .custom(strings.Channel_Status) } diff --git a/TelegramUI/ChatMediaInputNode.swift b/TelegramUI/ChatMediaInputNode.swift index e01bf46470..31ce75bdcb 100644 --- a/TelegramUI/ChatMediaInputNode.swift +++ b/TelegramUI/ChatMediaInputNode.swift @@ -1017,7 +1017,6 @@ final class ChatMediaInputNode: ChatInputNode { } private func updateAppearanceTransition(transition: ContainedViewLayoutTransition) { - var value: CGFloat = 1.0 - abs(self.currentCollectionListPanelOffset() / 41.0) value = min(1.0, max(0.0, value)) self.inputNodeInteraction.appearanceTransition = max(0.1, value) diff --git a/TelegramUI/ChatMessageActionItemNode.swift b/TelegramUI/ChatMessageActionItemNode.swift index 8d65a5e54b..1c154fbee6 100644 --- a/TelegramUI/ChatMessageActionItemNode.swift +++ b/TelegramUI/ChatMessageActionItemNode.swift @@ -353,17 +353,20 @@ private func universalServiceMessageString(theme: PresentationTheme?, strings: P } case let .phoneCall(_, discardReason, _): var titleString: String + let incoming: Bool if message.flags.contains(.Incoming) { titleString = strings.Notification_CallIncoming + incoming = true } else { titleString = strings.Notification_CallOutgoing + incoming = false } if let discardReason = discardReason { switch discardReason { case .busy, .disconnect: titleString = strings.Notification_CallCanceled case .missed: - titleString = strings.Notification_CallMissed + titleString = incoming ? strings.Notification_CallMissed : strings.Notification_CallCanceled case .hangup: break } diff --git a/TelegramUI/ChatMessageBubbleItemNode.swift b/TelegramUI/ChatMessageBubbleItemNode.swift index 7726128825..489656b161 100644 --- a/TelegramUI/ChatMessageBubbleItemNode.swift +++ b/TelegramUI/ChatMessageBubbleItemNode.swift @@ -263,7 +263,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { return false } for media in item.content.firstMessage.media { - if media is TelegramMediaAction { + if let media = media as? TelegramMediaAction, case .phoneCall(_, _, _) = media.action { + } else { return false } } diff --git a/TelegramUI/ChatMessageCallBubbleContentNode.swift b/TelegramUI/ChatMessageCallBubbleContentNode.swift index 95e31d6166..70c84258e4 100644 --- a/TelegramUI/ChatMessageCallBubbleContentNode.swift +++ b/TelegramUI/ChatMessageCallBubbleContentNode.swift @@ -83,7 +83,7 @@ class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode { titleString = item.presentationData.strings.Notification_CallCanceled case .missed: callSuccessful = false - titleString = item.presentationData.strings.Notification_CallMissed + titleString = incoming ? item.presentationData.strings.Notification_CallMissed : item.presentationData.strings.Notification_CallCanceled case .hangup: break } diff --git a/TelegramUI/ChatMessageContactBubbleContentNode.swift b/TelegramUI/ChatMessageContactBubbleContentNode.swift index a20d5c8223..98c6868de6 100644 --- a/TelegramUI/ChatMessageContactBubbleContentNode.swift +++ b/TelegramUI/ChatMessageContactBubbleContentNode.swift @@ -17,7 +17,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { private let textNode: TextNode private var contact: TelegramMediaContact? - private var contactPhone: String? + private var contactInfo : String? private let buttonNode: ChatMessageAttachedContentButtonNode @@ -56,7 +56,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { let makeButtonLayout = ChatMessageAttachedContentButtonNode.asyncLayout(self.buttonNode) let previousContact = self.contact - let previousContactPhone = self.contactPhone + let previousContactInfo = self.contactInfo return { item, layoutConstants, _, _, constrainedSize in var selectedContact: TelegramMediaContact? @@ -68,7 +68,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { var titleString: NSAttributedString? var textString: NSAttributedString? - var updatedPhone: String? + var updatedContactInfo: String? if let selectedContact = selectedContact { let displayName: String @@ -81,16 +81,45 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { } titleString = NSAttributedString(string: displayName, font: titleFont, textColor: item.message.effectivelyIncoming(item.account.peerId) ? item.presentationData.theme.theme.chat.bubble.incomingAccentTextColor : item.presentationData.theme.theme.chat.bubble.outgoingAccentTextColor) - let phone: String - if let previousContact = previousContact, previousContact.isEqual(to: selectedContact), let contactPhone = previousContactPhone { - phone = contactPhone + let info: String + if let previousContact = previousContact, previousContact.isEqual(to: selectedContact), let contactInfo = previousContactInfo { + info = contactInfo } else { - phone = formatPhoneNumber(selectedContact.phoneNumber) + if let vCard = selectedContact.vCardData, let vCardData = vCard.data(using: .utf8), let contactData = DeviceContactExtendedData(vcard: vCardData) { + let infoLineLimit = 5 + var infoComponents: [String] = [] + if !contactData.basicData.phoneNumbers.isEmpty { + for phone in contactData.basicData.phoneNumbers { + if infoComponents.count < infoLineLimit { + infoComponents.append(formatPhoneNumber(phone.value)) + } + } + } else { + infoComponents.append(formatPhoneNumber(selectedContact.phoneNumber)) + } + if infoComponents.count < infoLineLimit { + for email in contactData.emailAddresses { + if infoComponents.count < infoLineLimit { + infoComponents.append(email.value) + } + } + } + if infoComponents.count < infoLineLimit { + if !contactData.organization.isEmpty && (!contactData.basicData.firstName.isEmpty || !contactData.basicData.lastName.isEmpty) { + infoComponents.append(contactData.organization) + } + } + info = infoComponents.joined(separator: "\n") + } else { + info = formatPhoneNumber(selectedContact.phoneNumber) + } } - updatedPhone = phone - textString = NSAttributedString(string: phone, font: textFont, textColor: item.message.effectivelyIncoming(item.account.peerId) ? item.presentationData.theme.theme.chat.bubble.incomingPrimaryTextColor : item.presentationData.theme.theme.chat.bubble.outgoingPrimaryTextColor) + + updatedContactInfo = info + + textString = NSAttributedString(string: info, font: textFont, textColor: item.message.effectivelyIncoming(item.account.peerId) ? item.presentationData.theme.theme.chat.bubble.incomingPrimaryTextColor : item.presentationData.theme.theme.chat.bubble.outgoingPrimaryTextColor) } else { - updatedPhone = nil + updatedContactInfo = nil } let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) @@ -100,7 +129,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { let maxTextWidth = max(1.0, constrainedSize.width - avatarSize.width - layoutConstants.text.bubbleInsets.left - layoutConstants.text.bubbleInsets.right) let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: maxTextWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: textString, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: maxTextWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: textString, backgroundColor: nil, maximumNumberOfLines: 5, truncationType: .end, constrainedSize: CGSize(width: maxTextWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) var edited = false var sentViaBot = false @@ -186,7 +215,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { let (buttonSize, buttonApply) = continueLayout(boundingWidth - layoutConstants.text.bubbleInsets.right * 2.0) let buttonSpacing: CGFloat = 4.0 - layoutSize = CGSize(width: contentWidth, height: 66.0 + buttonSize.height + buttonSpacing) + layoutSize = CGSize(width: contentWidth, height: 49.0 + textLayout.size.height + buttonSize.height + buttonSpacing) statusFrame = CGRect(origin: CGPoint(x: boundingWidth - statusSize.width - layoutConstants.text.bubbleInsets.right, y: layoutSize.height - statusSize.height - 9.0 - buttonSpacing - buttonSize.height), size: statusSize) let buttonFrame = CGRect(origin: CGPoint(x: layoutConstants.text.bubbleInsets.right, y: layoutSize.height - 9.0 - buttonSize.height), size: buttonSize) let avatarFrame = baseAvatarFrame.offsetBy(dx: 5.0, dy: 5.0) @@ -208,7 +237,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { if let strongSelf = self { strongSelf.item = item strongSelf.contact = selectedContact - strongSelf.contactPhone = updatedPhone + strongSelf.contactInfo = updatedContactInfo strongSelf.avatarNode.frame = avatarFrame diff --git a/TelegramUI/ChatMessageGameBubbleContentNode.swift b/TelegramUI/ChatMessageGameBubbleContentNode.swift index 5b5b6c628a..68ab749879 100644 --- a/TelegramUI/ChatMessageGameBubbleContentNode.swift +++ b/TelegramUI/ChatMessageGameBubbleContentNode.swift @@ -22,6 +22,11 @@ final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNode { super.init() self.addSubnode(self.contentNode) + self.contentNode.openMedia = { [weak self] in + if let strongSelf = self, let item = strongSelf.item { + item.controllerInteraction.requestMessageActionCallback(item.message.id, nil, true) + } + } } required init?(coder aDecoder: NSCoder) { diff --git a/TelegramUI/ChatMessageInteractiveMediaNode.swift b/TelegramUI/ChatMessageInteractiveMediaNode.swift index 4526c4b590..c6aadd7098 100644 --- a/TelegramUI/ChatMessageInteractiveMediaNode.swift +++ b/TelegramUI/ChatMessageInteractiveMediaNode.swift @@ -528,7 +528,12 @@ final class ChatMessageInteractiveMediaNode: ASTransformNode { string.append(NSAttributedString(string: strings.Checkout_Receipt_Title.uppercased())) } else { string.append(NSAttributedString(string: "\(formatCurrencyAmount(invoice.totalAmount, currency: invoice.currency)) ", attributes: [ChatTextInputAttributes.bold: true as NSNumber])) - string.append(NSAttributedString(string: strings.Message_InvoiceLabel)) + + var title = strings.Message_InvoiceLabel + if invoice.flags.contains(.isTest) { + title += " (Test)" + } + string.append(NSAttributedString(string: title)) } badgeContent = .text(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, shape: .round, text: string) } diff --git a/TelegramUI/ChatMessageMapBubbleContentNode.swift b/TelegramUI/ChatMessageMapBubbleContentNode.swift index 1e80029749..c541141fea 100644 --- a/TelegramUI/ChatMessageMapBubbleContentNode.swift +++ b/TelegramUI/ChatMessageMapBubbleContentNode.swift @@ -337,7 +337,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode { strongSelf.addSubnode(liveTimerNode) } let timerSize = CGSize(width: 28.0, height: 28.0) - strongSelf.liveTimerNode?.frame = CGRect(origin: CGPoint(x: imageFrame.maxX - 10.0 - timerSize.width, y: imageFrame.maxY + 11.0), size: timerSize) + strongSelf.liveTimerNode?.frame = CGRect(origin: CGPoint(x: floor(imageFrame.maxX - 10.0 - timerSize.width), y: floor(imageFrame.maxY + 11.0)), size: timerSize) let timerForegroundColor: UIColor = item.message.effectivelyIncoming(item.account.peerId) ? item.presentationData.theme.theme.chat.bubble.incomingAccentControlColor : item.presentationData.theme.theme.chat.bubble.outgoingAccentControlColor let timerTextColor: UIColor = item.message.effectivelyIncoming(item.account.peerId) ? item.presentationData.theme.theme.chat.bubble.incomingSecondaryTextColor : item.presentationData.theme.theme.chat.bubble.outgoingSecondaryTextColor diff --git a/TelegramUI/ChatTitleView.swift b/TelegramUI/ChatTitleView.swift index 4c55751c0e..84a3f779d3 100644 --- a/TelegramUI/ChatTitleView.swift +++ b/TelegramUI/ChatTitleView.swift @@ -359,7 +359,14 @@ final class ChatTitleView: UIView, NavigationBarTitleView { } } else if let channel = peer as? TelegramChannel { if let cachedChannelData = peerView.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount { - let string = NSAttributedString(string: strings.Conversation_StatusMembers(memberCount), font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) + let membersString: String + if case .group = channel.info { + membersString = strings.Conversation_StatusMembers(memberCount) + } else { + membersString = strings.Conversation_StatusSubscribers(memberCount) + } + + let string = NSAttributedString(string: membersString, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) if self.infoNode.attributedText == nil || !self.infoNode.attributedText!.isEqual(to: string) { self.infoNode.attributedText = string shouldUpdateLayout = true diff --git a/TelegramUI/ContactInfoStrings.swift b/TelegramUI/ContactInfoStrings.swift index e794abfc8e..3d225c6deb 100644 --- a/TelegramUI/ContactInfoStrings.swift +++ b/TelegramUI/ContactInfoStrings.swift @@ -4,7 +4,13 @@ import AddressBook func localizedPhoneNumberLabel(label: String, strings: PresentationStrings) -> String { if #available(iOSApplicationExtension 9.0, *) { - return CNLabeledValue.localizedString(forLabel: label) + if label.isEmpty { + return strings.ContactInfo_PhoneLabelMain + } else if label == "X-iPhone" { + return "iPhone" + } else { + return CNLabeledValue.localizedString(forLabel: label) + } } else { } @@ -19,6 +25,9 @@ func localizedPhoneNumberLabel(label: String, strings: PresentationStrings) -> S func localizedGenericContactFieldLabel(label: String, strings: PresentationStrings) -> String { if #available(iOSApplicationExtension 9.0, *) { + if label.isEmpty { + return strings.ContactInfo_PhoneLabelMain + } return CNLabeledValue.localizedString(forLabel: label) } else { diff --git a/TelegramUI/DataAndStorageSettingsController.swift b/TelegramUI/DataAndStorageSettingsController.swift index 55c8289d8d..e86bcbbb00 100644 --- a/TelegramUI/DataAndStorageSettingsController.swift +++ b/TelegramUI/DataAndStorageSettingsController.swift @@ -44,11 +44,11 @@ private enum DataAndStorageEntry: ItemListNodeEntry { case networkUsage(PresentationTheme, String) case automaticMediaDownloadHeader(PresentationTheme, String) case automaticDownloadMaster(PresentationTheme, String, Bool) - case automaticDownloadPhoto(PresentationTheme, String) - case automaticDownloadVideo(PresentationTheme, String) - case automaticDownloadFile(PresentationTheme, String) - case automaticDownloadVoiceMessage(PresentationTheme, String) - case automaticDownloadVideoMessage(PresentationTheme, String) + case automaticDownloadPhoto(PresentationTheme, String, Bool) + case automaticDownloadVideo(PresentationTheme, String, Bool) + case automaticDownloadFile(PresentationTheme, String, Bool) + case automaticDownloadVoiceMessage(PresentationTheme, String, Bool) + case automaticDownloadVideoMessage(PresentationTheme, String, Bool) case automaticDownloadReset(PresentationTheme, String, Bool) case voiceCallsHeader(PresentationTheme, String) case useLessVoiceData(PresentationTheme, String, String) @@ -141,32 +141,32 @@ private enum DataAndStorageEntry: ItemListNodeEntry { } else { return false } - case let .automaticDownloadPhoto(lhsTheme, lhsText): - if case let .automaticDownloadPhoto(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + case let .automaticDownloadPhoto(lhsTheme, lhsText, lhsEnabled): + if case let .automaticDownloadPhoto(rhsTheme, rhsText, rhsEnabled) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsEnabled == rhsEnabled { return true } else { return false } - case let .automaticDownloadVideo(lhsTheme, lhsText): - if case let .automaticDownloadVideo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + case let .automaticDownloadVideo(lhsTheme, lhsText, lhsEnabled): + if case let .automaticDownloadVideo(rhsTheme, rhsText, rhsEnabled) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsEnabled == rhsEnabled { return true } else { return false } - case let .automaticDownloadFile(lhsTheme, lhsText): - if case let .automaticDownloadFile(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + case let .automaticDownloadFile(lhsTheme, lhsText, lhsEnabled): + if case let .automaticDownloadFile(rhsTheme, rhsText, rhsEnabled) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsEnabled == rhsEnabled { return true } else { return false } - case let .automaticDownloadVoiceMessage(lhsTheme, lhsText): - if case let .automaticDownloadVoiceMessage(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + case let .automaticDownloadVoiceMessage(lhsTheme, lhsText, lhsEnabled): + if case let .automaticDownloadVoiceMessage(rhsTheme, rhsText, rhsEnabled) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsEnabled == rhsEnabled { return true } else { return false } - case let .automaticDownloadVideoMessage(lhsTheme, lhsText): - if case let .automaticDownloadVideoMessage(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + case let .automaticDownloadVideoMessage(lhsTheme, lhsText, lhsEnabled): + if case let .automaticDownloadVideoMessage(rhsTheme, rhsText, rhsEnabled) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsEnabled == rhsEnabled { return true } else { return false @@ -248,30 +248,40 @@ private enum DataAndStorageEntry: ItemListNodeEntry { return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in arguments.toggleAutomaticDownloadMaster(value) }) - case let .automaticDownloadPhoto(theme, text): - return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { - arguments.openAutomaticDownloadCategory(.photo) + case let .automaticDownloadPhoto(theme, text, enabled): + return ItemListDisclosureItem(theme: theme, title: text, kind: enabled ? .generic : .disabled, label: "", sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + if enabled { + arguments.openAutomaticDownloadCategory(.photo) + } }) - case let .automaticDownloadVideo(theme, text): - return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { - arguments.openAutomaticDownloadCategory(.video) + case let .automaticDownloadVideo(theme, text, enabled): + return ItemListDisclosureItem(theme: theme, title: text, kind: enabled ? .generic : .disabled, label: "", sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + if enabled { + arguments.openAutomaticDownloadCategory(.video) + } }) - case let .automaticDownloadFile(theme, text): - return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { - arguments.openAutomaticDownloadCategory(.file) + case let .automaticDownloadFile(theme, text, enabled): + return ItemListDisclosureItem(theme: theme, title: text, kind: enabled ? .generic : .disabled, label: "", sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + if enabled { + arguments.openAutomaticDownloadCategory(.file) + } }) - case let .automaticDownloadVoiceMessage(theme, text): - return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { - arguments.openAutomaticDownloadCategory(.voiceMessage) + case let .automaticDownloadVoiceMessage(theme, text, enabled): + return ItemListDisclosureItem(theme: theme, title: text, kind: enabled ? .generic : .disabled, label: "", sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + if enabled { + arguments.openAutomaticDownloadCategory(.voiceMessage) + } }) - case let .automaticDownloadVideoMessage(theme, text): - return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { - arguments.openAutomaticDownloadCategory(.videoMessage) + case let .automaticDownloadVideoMessage(theme, text, enabled): + return ItemListDisclosureItem(theme: theme, title: text, kind: enabled ? .generic : .disabled, label: "", sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + if enabled { + arguments.openAutomaticDownloadCategory(.videoMessage) + } }) case let .automaticDownloadReset(theme, text, enabled): return ItemListActionItem(theme: theme, title: text, kind: enabled ? .generic : .disabled, alignment: .natural, sectionId: self.section, style: .blocks, action: { if enabled { - arguments.resetAutomaticDownload() + arguments.resetAutomaticDownload() } }) case let .voiceCallsHeader(theme, text): @@ -347,11 +357,11 @@ private func dataAndStorageControllerEntries(state: DataAndStorageControllerStat entries.append(.automaticMediaDownloadHeader(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadTitle)) entries.append(.automaticDownloadMaster(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadEnabled, data.automaticMediaDownloadSettings.masterEnabled)) - entries.append(.automaticDownloadPhoto(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadPhotos)) - entries.append(.automaticDownloadVideo(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadVideos)) - entries.append(.automaticDownloadFile(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadDocuments)) - entries.append(.automaticDownloadVoiceMessage(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadVoiceMessages)) - entries.append(.automaticDownloadVideoMessage(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadVideoMessages)) + entries.append(.automaticDownloadPhoto(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadPhotos, data.automaticMediaDownloadSettings.masterEnabled)) + entries.append(.automaticDownloadVideo(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadVideos, data.automaticMediaDownloadSettings.masterEnabled)) + entries.append(.automaticDownloadFile(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadDocuments, data.automaticMediaDownloadSettings.masterEnabled)) + entries.append(.automaticDownloadVoiceMessage(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadVoiceMessages, data.automaticMediaDownloadSettings.masterEnabled)) + entries.append(.automaticDownloadVideoMessage(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadVideoMessages,data.automaticMediaDownloadSettings.masterEnabled)) entries.append(.automaticDownloadReset(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadReset, data.automaticMediaDownloadSettings.peers != AutomaticMediaDownloadSettings.defaultSettings.peers || !data.automaticMediaDownloadSettings.masterEnabled)) entries.append(.voiceCallsHeader(presentationData.theme, presentationData.strings.Settings_CallSettings.uppercased())) diff --git a/TelegramUI/DataPrivacySettingsController.swift b/TelegramUI/DataPrivacySettingsController.swift index 962205523a..c3d00cd7b8 100644 --- a/TelegramUI/DataPrivacySettingsController.swift +++ b/TelegramUI/DataPrivacySettingsController.swift @@ -298,32 +298,71 @@ public func dataPrivacyController(account: Account) -> ViewController { let dismissAction: () -> Void = { [weak controller] in controller?.dismissAnimated() } - controller.setItemGroups([ - ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: presentationData.strings.Privacy_PaymentsClearInfo, color: .destructive, action: { - var clear = false - updateState { state in - var state = state - if !state.clearingPaymentInfo { - clear = true - state.clearingPaymentInfo = true + + var values = [true, true] + + let toggleCheck: (Int) -> Void = { [weak controller] itemIndex in + controller?.updateItem(groupIndex: 0, itemIndex: itemIndex, { item in + if let item = item as? ActionSheetCheckboxItem { + values[itemIndex] = !item.value + return ActionSheetCheckboxItem(title: item.title, label: item.label, value: !item.value, action: item.action) + } + return item + }) + + controller?.updateItem(groupIndex: 0, itemIndex: 2, { item in + if let item = item as? ActionSheetButtonItem { + let disabled = !values[0] && !values[1] + return ActionSheetButtonItem(title: item.title, color: disabled ? .disabled : .accent, enabled: !disabled, action: item.action) + } + return item + }) + } + + var items: [ActionSheetItem] = [] + + items.append(ActionSheetCheckboxItem(title: presentationData.strings.Privacy_PaymentsClear_PaymentInfo, label: "", value: true, action: { value in + toggleCheck(0) + })) + + items.append(ActionSheetCheckboxItem(title: presentationData.strings.Privacy_PaymentsClear_ShippingInfo, label: "", value: true, action: { value in + toggleCheck(1) + })) + + items.append(ActionSheetButtonItem(title: presentationData.strings.Cache_ClearNone, action: { + var clear = false + updateState { state in + var state = state + if !state.clearingPaymentInfo { + clear = true + state.clearingPaymentInfo = true + } + return state + } + if clear { + var info = BotPaymentInfo() + if values[0] { + info.insert(.paymentInfo) + } + if values[1] { + info.insert(.shippingInfo) + } + + clearPaymentInfoDisposable.set((clearBotPaymentInfo(network: account.network, info: info) + |> deliverOnMainQueue).start(completed: { + updateState { state in + var state = state + state.clearingPaymentInfo = false + return state } - return state - } - if clear { - clearPaymentInfoDisposable.set((clearBotPaymentInfo(network: account.network) - |> deliverOnMainQueue).start(completed: { - updateState { state in - var state = state - state.clearingPaymentInfo = false - return state - } - presentControllerImpl?(OverlayStatusController(theme: account.telegramApplicationContext.currentPresentationData.with({ $0 }).theme, type: .success)) - })) - } - dismissAction() - }) - ]), + presentControllerImpl?(OverlayStatusController(theme: account.telegramApplicationContext.currentPresentationData.with({ $0 }).theme, type: .success)) + })) + } + dismissAction() + })) + + controller.setItemGroups([ + ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) ]) presentControllerImpl?(controller) diff --git a/TelegramUI/DefaultDarkAccentPresentationTheme.swift b/TelegramUI/DefaultDarkAccentPresentationTheme.swift index d3b1831b43..efdd0aac41 100644 --- a/TelegramUI/DefaultDarkAccentPresentationTheme.swift +++ b/TelegramUI/DefaultDarkAccentPresentationTheme.swift @@ -66,6 +66,7 @@ private let list = PresentationThemeList( itemSecondaryTextColor: UIColor(rgb: 0xDBF5FF, alpha: 0.5), itemDisabledTextColor: UIColor(rgb: 0xDBF5FF, alpha: 0.5), //!!! itemAccentColor: accentColor, + itemHighlightedColor: UIColor(rgb: 0x28b772), itemDestructiveColor: destructiveColor, itemPlaceholderTextColor: UIColor(rgb: 0xDBF5FF, alpha: 0.5), //!!! itemBlocksBackgroundColor: UIColor(rgb: 0x213040), @@ -177,7 +178,7 @@ private let bubble = PresentationThemeChatBubble( selectionControlBorderColor: .white, selectionControlFillColor: accentColor, selectionControlForegroundColor: .white, - mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.4) + mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.6) ) private let serviceMessage = PresentationThemeServiceMessage( diff --git a/TelegramUI/DefaultDarkPresentationTheme.swift b/TelegramUI/DefaultDarkPresentationTheme.swift index 561c12e819..010f62b71b 100644 --- a/TelegramUI/DefaultDarkPresentationTheme.swift +++ b/TelegramUI/DefaultDarkPresentationTheme.swift @@ -66,6 +66,7 @@ private let list = PresentationThemeList( itemSecondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), itemDisabledTextColor: UIColor(rgb: 0x4d4d4d), //!!! itemAccentColor: accentColor, + itemHighlightedColor: UIColor(rgb: 0x28b772), itemDestructiveColor: destructiveColor, itemPlaceholderTextColor: UIColor(rgb: 0x4d4d4d), //!!! itemBlocksBackgroundColor: UIColor(rgb: 0x1c1c1d), @@ -177,7 +178,7 @@ private let bubble = PresentationThemeChatBubble( selectionControlBorderColor: .white, selectionControlFillColor: accentColor, selectionControlForegroundColor: .black, - mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.4) + mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.6) ) private let serviceMessage = PresentationThemeServiceMessage( diff --git a/TelegramUI/DefaultPresentationTheme.swift b/TelegramUI/DefaultPresentationTheme.swift index b38c1d8c3a..af39a49f17 100644 --- a/TelegramUI/DefaultPresentationTheme.swift +++ b/TelegramUI/DefaultPresentationTheme.swift @@ -66,6 +66,7 @@ private func makeDefaultPresentationTheme(accentColor: UIColor, day: Bool) -> Pr itemSecondaryTextColor: UIColor(rgb: 0x8e8e93), itemDisabledTextColor: UIColor(rgb: 0x8e8e93), itemAccentColor: accentColor, + itemHighlightedColor: secretColor, itemDestructiveColor: destructiveColor, itemPlaceholderTextColor: UIColor(rgb: 0xc8c8ce), itemBlocksBackgroundColor: .white, @@ -207,7 +208,7 @@ private func makeDefaultPresentationTheme(accentColor: UIColor, day: Bool) -> Pr selectionControlBorderColor: UIColor(rgb: 0xC7C7CC), selectionControlFillColor: accentColor, selectionControlForegroundColor: .white, - mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.2) + mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.6) ) let bubbleDay = PresentationThemeChatBubble( @@ -257,7 +258,7 @@ private func makeDefaultPresentationTheme(accentColor: UIColor, day: Bool) -> Pr selectionControlBorderColor: UIColor(rgb: 0xC7C7CC), selectionControlFillColor: accentColor, selectionControlForegroundColor: .white, - mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.2) + mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.6) ) let serviceMessage = PresentationThemeServiceMessage( diff --git a/TelegramUI/DeviceContactData.swift b/TelegramUI/DeviceContactData.swift index 71a1fc13a9..325f9ba215 100644 --- a/TelegramUI/DeviceContactData.swift +++ b/TelegramUI/DeviceContactData.swift @@ -124,11 +124,13 @@ public final class DeviceContactSocialProfileData: Equatable, Hashable { public let label: String public let service: String public let username: String + public let url: String - public init(label: String, service: String, username: String) { + public init(label: String, service: String, username: String, url: String) { self.label = label self.service = service self.username = username + self.url = url } public static func == (lhs: DeviceContactSocialProfileData, rhs: DeviceContactSocialProfileData) -> Bool { @@ -141,6 +143,9 @@ public final class DeviceContactSocialProfileData: Equatable, Hashable { if lhs.username != rhs.username { return false } + if lhs.url != rhs.url { + return false + } return true } @@ -149,6 +154,7 @@ public final class DeviceContactSocialProfileData: Equatable, Hashable { result = result &* 31 &+ self.label.hashValue result = result &* 31 &+ self.service.hashValue result = result &* 31 &+ self.username.hashValue + result = result &* 31 &+ self.url.hashValue return result } } @@ -373,7 +379,7 @@ extension DeviceContactExtendedData { } var socialProfiles: [DeviceContactSocialProfileData] = [] for profile in contact.socialProfiles { - socialProfiles.append(DeviceContactSocialProfileData(label: profile.label ?? "", service: profile.value.service, username: profile.value.username)) + socialProfiles.append(DeviceContactSocialProfileData(label: profile.label ?? "", service: profile.value.service, username: profile.value.username, url: profile.value.urlString)) } var instantMessagingProfiles: [DeviceContactInstantMessagingProfileData] = [] diff --git a/TelegramUI/DeviceContactInfoController.swift b/TelegramUI/DeviceContactInfoController.swift index 4c1e1ddfcb..313e7d5fc7 100644 --- a/TelegramUI/DeviceContactInfoController.swift +++ b/TelegramUI/DeviceContactInfoController.swift @@ -401,23 +401,38 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry { if selected != nil { arguments.toggleSelection(.birthday) } else { - //arguments.openUrl("mailto:\(value)") + let calendar = Calendar(identifier: .gregorian) + var components = calendar.dateComponents([.month, .day], from: value) + let currentComponents = calendar.dateComponents([.year, .month, .day], from: Date()) + + if let month = components.month, let currentMonth = currentComponents.month, let day = components.day, let currentDay = currentComponents.day, let currentYear = currentComponents.year { + if month >= currentMonth && (day >= currentDay || month > currentMonth) { + components.year = currentYear + } else { + components.year = currentYear + 1 + } + components.hour = 12 + components.minute = 0 + + if let targetDate = calendar.date(from: components) { + let url = "calshow:\(targetDate.timeIntervalSinceReferenceDate)" + arguments.openUrl(url) + } + } } }, tag: nil) case let .socialProfile(_, _, theme, title, value, text, selected): return ItemListTextWithLabelItem(theme: theme, label: title, text: text, textColor: .accent, enabledEntitiyTypes: [], multiline: true, selected: selected, sectionId: self.section, action: { if selected != nil { arguments.toggleSelection(.socialProfile(value)) - } else { - //arguments.openUrl("mailto:\(value)") + } else if value.url.count > 0 { + arguments.openUrl(value.url) } }, tag: nil) case let .instantMessenger(_, _, theme, title, value, text, selected): return ItemListTextWithLabelItem(theme: theme, label: title, text: text, textColor: .accent, enabledEntitiyTypes: [], multiline: true, selected: selected, sectionId: self.section, action: { if selected != nil { arguments.toggleSelection(.instantMessenger(value)) - } else { - //arguments.openUrl("mailto:\(value)") } }, tag: nil) } @@ -486,26 +501,32 @@ private func deviceContactInfoEntries(account: Account, presentationData: Presen editingName = editingState.editingName } - var jobSummary: String? - if !contactData.organization.isEmpty { - jobSummary = contactData.organization - } else if !contactData.department.isEmpty { - jobSummary = contactData.department - } else if !contactData.jobTitle.isEmpty { - jobSummary = contactData.jobTitle - } - var personName: (String, String) = (contactData.basicData.firstName, contactData.basicData.lastName) if let editingName = editingName { switch editingName { - case let .personName(firstName, lastName): - personName = (firstName, lastName) - default: - break + case let .personName(firstName, lastName): + personName = (firstName, lastName) + default: + break } } - entries.append(.info(entries.count, presentationData.theme, presentationData.strings, peer: peer ?? TelegramUser(id: PeerId(namespace: -1, id: 0), accessHash: nil, firstName: personName.0, lastName: personName.1, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []), state: ItemListAvatarAndNameInfoItemState(editingName: editingName, updatingName: nil), job: jobSummary)) + var jobComponents: [String] = [] + if !contactData.organization.isEmpty { + jobComponents.append(contactData.organization) + } + if !contactData.department.isEmpty { + jobComponents.append(contactData.department) + } + if !contactData.jobTitle.isEmpty { + jobComponents.append(contactData.jobTitle) + } + let jobSummary = jobComponents.joined(separator: " — ") + + let isOrganization = personName.0.isEmpty && personName.1.isEmpty && !contactData.organization.isEmpty + + + entries.append(.info(entries.count, presentationData.theme, presentationData.strings, peer: peer ?? TelegramUser(id: PeerId(namespace: -1, id: 0), accessHash: nil, firstName: isOrganization ? contactData.organization : personName.0, lastName: isOrganization ? nil : personName.1, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []), state: ItemListAvatarAndNameInfoItemState(editingName: editingName, updatingName: nil), job: isOrganization ? nil : jobSummary)) if !selecting { if let _ = peer { @@ -522,7 +543,8 @@ private func deviceContactInfoEntries(account: Account, presentationData: Presen if editingPhoneNumbers { for number in state.phoneNumbers { - entries.append(.editingPhoneNumber(entries.count, presentationData.theme, presentationData.strings, number.id, localizedPhoneNumberLabel(label: number.label, strings: presentationData.strings), number.label, number.value, state.phoneIdWithRevealedOptions == number.id)) + let label = !number.label.isEmpty ? number.label : presentationData.strings.ContactInfo_PhoneLabelMain + entries.append(.editingPhoneNumber(entries.count, presentationData.theme, presentationData.strings, number.id, localizedPhoneNumberLabel(label: label, strings: presentationData.strings), number.label, number.value, state.phoneIdWithRevealedOptions == number.id)) } entries.append(.addPhoneNumber(entries.count, presentationData.theme, presentationData.strings.UserInfo_AddPhone)) } else { @@ -970,7 +992,6 @@ func deviceContactInfoController(account: Account, subject: DeviceContactInfoSub guard let _ = controller else { return } - } openUrlImpl = { [weak controller] url in guard let controller = controller else { diff --git a/TelegramUI/EditableTokenListNode.swift b/TelegramUI/EditableTokenListNode.swift index df90ef76a9..408ada9122 100644 --- a/TelegramUI/EditableTokenListNode.swift +++ b/TelegramUI/EditableTokenListNode.swift @@ -109,6 +109,7 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate { self.theme = theme self.scrollNode = ASScrollNode() + self.scrollNode.view.alwaysBounceVertical = true self.placeholderNode = ASTextNode() self.placeholderNode.isLayerBacked = true @@ -138,12 +139,13 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate { self.separatorNode.backgroundColor = theme.separatorColor super.init() + self.addSubnode(self.scrollNode) self.backgroundColor = theme.backgroundColor - self.addSubnode(self.placeholderNode) self.addSubnode(self.separatorNode) - self.addSubnode(self.textFieldNode) - self.addSubnode(self.caretIndicatorNode) + self.scrollNode.addSubnode(self.placeholderNode) + self.scrollNode.addSubnode(self.textFieldNode) + self.scrollNode.addSubnode(self.caretIndicatorNode) self.clipsToBounds = true self.textFieldNode.textField.delegate = self @@ -209,7 +211,7 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate { } else { tokenNode = TokenNode(theme: self.theme, token: token, isSelected: self.selectedTokenId != nil && token.id == self.selectedTokenId!) self.tokenNodes.append(tokenNode) - self.addSubnode(tokenNode) + self.scrollNode.addSubnode(tokenNode) animateIn = true } @@ -278,10 +280,26 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate { self.caretIndicatorNode.layer.animateFrame(from: previousCaretFrame, to: caretNodeFrame, duration: 0.2 + animationDelay, timingFunction: kCAMediaTimingFunctionSpring) } - let nodeHeight = currentOffset.y + 29.0 + verticalInset + let previousContentHeight = self.scrollNode.view.contentSize.height + let contentHeight = currentOffset.y + 29.0 + verticalInset + let nodeHeight = min(contentHeight, 110.0) let separatorHeight = UIScreenPixel transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: nodeHeight - separatorHeight), size: CGSize(width: width, height: separatorHeight))) + transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: nodeHeight))) + + if !fabs(previousContentHeight - contentHeight).isLess(than: CGFloat.ulpOfOne) { + let contentOffset = CGPoint(x: 0, y: max(0, contentHeight - nodeHeight)) + if case .immediate = transition { + self.scrollNode.view.contentOffset = contentOffset + } + else { + UIView.animate(withDuration: 0.2) { + self.scrollNode.view.contentOffset = contentOffset + } + } + } + self.scrollNode.view.contentSize = CGSize(width: width, height: contentHeight) return nodeHeight } @@ -299,8 +317,8 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate { } func textFieldDidEndEditing(_ textField: UITextField) { - if self.caretIndicatorNode.supernode != self { - self.addSubnode(self.caretIndicatorNode) + if self.caretIndicatorNode.supernode != self.scrollNode { + self.scrollNode.addSubnode(self.caretIndicatorNode) } } diff --git a/TelegramUI/GalleryThumbnailContainerNode.swift b/TelegramUI/GalleryThumbnailContainerNode.swift index fcbac4e3e2..1be8aad4e5 100644 --- a/TelegramUI/GalleryThumbnailContainerNode.swift +++ b/TelegramUI/GalleryThumbnailContainerNode.swift @@ -44,9 +44,9 @@ private final class GalleryThumbnailItemNode: ASDisplayNode { } } -final class GalleryThumbnailContainerNode: ASDisplayNode { +final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDelegate { let groupId: Int64 - private let contentNode: ASDisplayNode + private let scrollNode: ASScrollNode private(set) var items: [GalleryThumbnailItem] = [] private var itemNodes: [GalleryThumbnailItemNode] = [] @@ -55,11 +55,13 @@ final class GalleryThumbnailContainerNode: ASDisplayNode { init(groupId: Int64) { self.groupId = groupId - self.contentNode = ASDisplayNode() - + self.scrollNode = ASScrollNode() + super.init() - - self.addSubnode(self.contentNode) + + self.scrollNode.view.delegate = self + + self.addSubnode(self.scrollNode) } func updateItems(_ items: [GalleryThumbnailItem], centralIndex: Int, progress: CGFloat) { @@ -86,7 +88,7 @@ final class GalleryThumbnailContainerNode: ASDisplayNode { for itemNode in itemNodes { if itemNode.supernode == nil { - self.contentNode.addSubnode(itemNode) + self.scrollNode.addSubnode(itemNode) } } for itemNode in self.itemNodes { @@ -119,7 +121,7 @@ final class GalleryThumbnailContainerNode: ASDisplayNode { func updateLayout(size: CGSize, centralIndex: Int, progress: CGFloat, transition: ContainedViewLayoutTransition) { self.currentLayout = size - self.contentNode.frame = CGRect(origin: CGPoint(), size: size) + self.scrollNode.frame = CGRect(origin: CGPoint(), size: size) let spacing: CGFloat = 2.0 let centralSpacing: CGFloat = 8.0 let itemHeight: CGFloat = 42.0 diff --git a/TelegramUI/InstalledStickerPacksController.swift b/TelegramUI/InstalledStickerPacksController.swift index 533121fd1a..a5197825e4 100644 --- a/TelegramUI/InstalledStickerPacksController.swift +++ b/TelegramUI/InstalledStickerPacksController.swift @@ -236,7 +236,7 @@ private enum InstalledStickerPacksEntry: ItemListNodeEntry { arguments.openSuggestOptions() }) case let .trending(theme, text, count): - return ItemListDisclosureItem(theme: theme, title: text, label: count == 0 ? "" : "\(count)", sectionId: self.section, style: .blocks, action: { + return ItemListDisclosureItem(theme: theme, title: text, label: count == 0 ? "" : "\(count)", labelStyle: .badge, sectionId: self.section, style: .blocks, action: { arguments.openFeatured() }) case let .masks(theme, text): diff --git a/TelegramUI/ItemListActionItem.swift b/TelegramUI/ItemListActionItem.swift index c554174fea..0e78b13172 100644 --- a/TelegramUI/ItemListActionItem.swift +++ b/TelegramUI/ItemListActionItem.swift @@ -175,12 +175,10 @@ class ItemListActionItemNode: ListViewItemNode { let _ = titleApply() - let leftInset: CGFloat + let leftInset = 16.0 + params.leftInset switch item.style { case .plain: - leftInset = 35.0 + params.leftInset - if strongSelf.backgroundNode.supernode != nil { strongSelf.backgroundNode.removeFromSupernode() } @@ -193,8 +191,6 @@ class ItemListActionItemNode: ListViewItemNode { strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight)) case .blocks: - leftInset = 16.0 + params.leftInset - if strongSelf.backgroundNode.supernode == nil { strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0) } diff --git a/TelegramUI/ItemListAvatarAndNameItem.swift b/TelegramUI/ItemListAvatarAndNameItem.swift index f191f3abc9..bbaaff7887 100644 --- a/TelegramUI/ItemListAvatarAndNameItem.swift +++ b/TelegramUI/ItemListAvatarAndNameItem.swift @@ -422,7 +422,11 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite } } else if let channel = item.peer as? TelegramChannel { if let cachedChannelData = item.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount { - statusText = item.strings.GroupInfo_ParticipantCount(memberCount) + if case .group = channel.info { + statusText = item.strings.Conversation_StatusMembers(memberCount) + } else { + statusText = item.strings.Conversation_StatusSubscribers(memberCount) + } statusColor = item.theme.list.itemSecondaryTextColor } else { switch channel.info { diff --git a/TelegramUI/ItemListDisclosureItem.swift b/TelegramUI/ItemListDisclosureItem.swift index dd510b4a13..125b944f43 100644 --- a/TelegramUI/ItemListDisclosureItem.swift +++ b/TelegramUI/ItemListDisclosureItem.swift @@ -19,11 +19,17 @@ enum ItemListDisclosureLabelStyle { case color(UIColor) } +enum ItemListDisclosureKind { + case generic + case disabled +} + class ItemListDisclosureItem: ListViewItem, ItemListItem { let theme: PresentationTheme let icon: UIImage? let title: String let titleColor: ItemListDisclosureItemTitleColor + let kind: ItemListDisclosureKind let label: String let labelStyle: ItemListDisclosureLabelStyle let sectionId: ItemListSectionId @@ -31,11 +37,12 @@ class ItemListDisclosureItem: ListViewItem, ItemListItem { let disclosureStyle: ItemListDisclosureStyle let action: (() -> Void)? - init(theme: PresentationTheme, icon: UIImage? = nil, title: String, titleColor: ItemListDisclosureItemTitleColor = .primary, label: String, labelStyle: ItemListDisclosureLabelStyle = .text, sectionId: ItemListSectionId, style: ItemListStyle, disclosureStyle: ItemListDisclosureStyle = .arrow, action: (() -> Void)?) { + init(theme: PresentationTheme, icon: UIImage? = nil, title: String, kind: ItemListDisclosureKind = .generic, titleColor: ItemListDisclosureItemTitleColor = .primary, label: String, labelStyle: ItemListDisclosureLabelStyle = .text, sectionId: ItemListSectionId, style: ItemListStyle, disclosureStyle: ItemListDisclosureStyle = .arrow, action: (() -> Void)?) { self.theme = theme self.icon = icon self.title = title self.titleColor = titleColor + self.kind = kind self.labelStyle = labelStyle self.label = label self.sectionId = sectionId @@ -84,6 +91,7 @@ class ItemListDisclosureItem: ListViewItem, ItemListItem { } private let titleFont = Font.regular(17.0) +private let badgeFont = Font.regular(15.0) class ItemListDisclosureItemNode: ListViewItemNode { private let backgroundNode: ASDisplayNode @@ -175,7 +183,7 @@ class ItemListDisclosureItemNode: ListViewItemNode { var hasBadge = false if case .badge = item.labelStyle { - hasBadge = true + hasBadge = item.label.count > 0 } if case let .color(color) = item.labelStyle { var updatedColor = true @@ -187,14 +195,15 @@ class ItemListDisclosureItemNode: ListViewItemNode { } } + let badgeDiameter: CGFloat = 20.0 if currentItem?.theme !== item.theme { updatedTheme = item.theme updateArrowImage = PresentationResourcesItemList.disclosureArrowImage(item.theme) if hasBadge { - updatedLabelBadgeImage = generateStretchableFilledCircleImage(diameter: 20.0, color: item.theme.list.itemAccentColor) + updatedLabelBadgeImage = generateStretchableFilledCircleImage(diameter: badgeDiameter, color: item.theme.list.itemAccentColor) } } else if hasBadge && !currentHasBadge { - updatedLabelBadgeImage = generateStretchableFilledCircleImage(diameter: 20.0, color: item.theme.list.itemAccentColor) + updatedLabelBadgeImage = generateStretchableFilledCircleImage(diameter: badgeDiameter, color: item.theme.list.itemAccentColor) } var updateIcon = false @@ -208,17 +217,15 @@ class ItemListDisclosureItemNode: ListViewItemNode { let itemBackgroundColor: UIColor let itemSeparatorColor: UIColor - var leftInset: CGFloat = params.leftInset + var leftInset = 16.0 + params.leftInset switch item.style { case .plain: - leftInset += 35.0 itemBackgroundColor = item.theme.list.plainBackgroundColor itemSeparatorColor = item.theme.list.itemPlainSeparatorColor contentSize = CGSize(width: params.width, height: 44.0) insets = itemListNeighborsPlainInsets(neighbors) case .blocks: - leftInset += 16.0 itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor contentSize = CGSize(width: params.width, height: 44.0) @@ -229,8 +236,26 @@ class ItemListDisclosureItemNode: ListViewItemNode { leftInset += 43.0 } - let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.titleColor == .accent ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.label, font: titleFont, textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset - 40.0 - titleLayout.size.width - 10.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + let labelFont: UIFont + let labelBadgeColor: UIColor + if case .badge = item.labelStyle { + labelBadgeColor = item.theme.list.plainBackgroundColor + labelFont = badgeFont + } else { + labelBadgeColor = item.theme.list.itemSecondaryTextColor + labelFont = titleFont + } + + let titleColor: UIColor + switch item.kind { + case .generic: + titleColor = item.titleColor == .accent ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor + case .disabled: + titleColor = item.theme.list.itemDisabledTextColor + } + + let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.label, font: labelFont, textColor:labelBadgeColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset - 40.0 - titleLayout.size.width - 10.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) @@ -308,7 +333,26 @@ class ItemListDisclosureItemNode: ListViewItemNode { } strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 11.0), size: titleLayout.size) - strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: params.width - rightInset - labelLayout.size.width, y: 11.0), size: labelLayout.size) + + let labelY: CGFloat + if case .badge = item.labelStyle { + labelY = 13.0 + } else { + labelY = 11.0 + } + strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: params.width - rightInset - labelLayout.size.width, y: labelY), size: labelLayout.size) + + if let updateBadgeImage = updatedLabelBadgeImage { + if strongSelf.labelBadgeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.labelBadgeNode, belowSubnode: strongSelf.labelNode) + } + strongSelf.labelBadgeNode.image = updateBadgeImage + } + if !hasBadge && strongSelf.labelBadgeNode.supernode != nil { + strongSelf.labelBadgeNode.image = nil + strongSelf.labelBadgeNode.removeFromSupernode() + } + strongSelf.labelBadgeNode.frame = CGRect(origin: CGPoint(x: params.width - rightInset - labelLayout.size.width - 5.0, y: 12.0), size: CGSize(width: max(badgeDiameter, labelLayout.size.width + 10.0), height: badgeDiameter)) if case .color = item.labelStyle { if let updatedLabelImage = updatedLabelImage { @@ -345,7 +389,7 @@ class ItemListDisclosureItemNode: ListViewItemNode { override func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) { super.setHighlighted(highlighted, at: point, animated: animated) - if highlighted { + if highlighted && self.item?.kind != ItemListDisclosureKind.disabled { self.highlightedBackgroundNode.alpha = 1.0 if self.highlightedBackgroundNode.supernode == nil { var anchorNode: ASDisplayNode? diff --git a/TelegramUI/ItemListMultilineInputItem.swift b/TelegramUI/ItemListMultilineInputItem.swift index 18370e3b66..b65c33525a 100644 --- a/TelegramUI/ItemListMultilineInputItem.swift +++ b/TelegramUI/ItemListMultilineInputItem.swift @@ -130,16 +130,14 @@ class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNodeDelega let itemBackgroundColor: UIColor let itemSeparatorColor: UIColor - let leftInset: CGFloat + let leftInset = 16.0 + params.rightInset switch item.style { - case .blocks: - itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor - itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor - leftInset = 16.0 + params.leftInset case .plain: itemBackgroundColor = item.theme.list.plainBackgroundColor itemSeparatorColor = item.theme.list.itemPlainSeparatorColor - leftInset = 35.0 + params.rightInset + case .blocks: + itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor + itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor } var limitTextString: NSAttributedString? @@ -267,23 +265,14 @@ class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNodeDelega let insets = self.insets let contentSize = CGSize(width: params.width, height: max(1.0, currentValue - insets.top - insets.bottom)) - if let item = self.item { - let leftInset: CGFloat - switch item.style { - case .blocks: - leftInset = 16.0 + params.leftInset - case .plain: - leftInset = 35.0 + params.leftInset - } - - let textTopInset: CGFloat = 11.0 - let textBottomInset: CGFloat = 11.0 - - self.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) - self.bottomStripeNode.frame = CGRect(origin: CGPoint(x: self.bottomStripeNode.frame.minX, y: contentSize.height), size: CGSize(width: self.bottomStripeNode.frame.size.width, height: separatorHeight)) - - self.textClippingNode.frame = CGRect(origin: CGPoint(x: leftInset, y: textTopInset), size: CGSize(width: max(0.0, params.width - leftInset - params.rightInset), height: max(0.0, contentSize.height - textTopInset - textBottomInset))) - } + let leftInset = 16.0 + params.leftInset + let textTopInset: CGFloat = 11.0 + let textBottomInset: CGFloat = 11.0 + + self.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + self.bottomStripeNode.frame = CGRect(origin: CGPoint(x: self.bottomStripeNode.frame.minX, y: contentSize.height), size: CGSize(width: self.bottomStripeNode.frame.size.width, height: separatorHeight)) + + self.textClippingNode.frame = CGRect(origin: CGPoint(x: leftInset, y: textTopInset), size: CGSize(width: max(0.0, params.width - leftInset - params.rightInset), height: max(0.0, contentSize.height - textTopInset - textBottomInset))) } func editableTextNodeDidUpdateText(_ editableTextNode: ASEditableTextNode) { diff --git a/TelegramUI/ItemListMultilineTextItem.swift b/TelegramUI/ItemListMultilineTextItem.swift index dd818cf4c4..0c5c3b1ec9 100644 --- a/TelegramUI/ItemListMultilineTextItem.swift +++ b/TelegramUI/ItemListMultilineTextItem.swift @@ -167,7 +167,7 @@ class ItemListMultilineTextItemNode: ListViewItemNode { case .plain: itemBackgroundColor = item.theme.list.plainBackgroundColor itemSeparatorColor = item.theme.list.itemPlainSeparatorColor - leftInset = 35.0 + params.leftInset + leftInset = 16.0 + params.leftInset case .blocks: itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor diff --git a/TelegramUI/ItemListRevealOptionsNode.swift b/TelegramUI/ItemListRevealOptionsNode.swift index ba85e9b404..518590511b 100644 --- a/TelegramUI/ItemListRevealOptionsNode.swift +++ b/TelegramUI/ItemListRevealOptionsNode.swift @@ -1,7 +1,7 @@ import Foundation import AsyncDisplayKit import Display -//import Lottie +import Lottie struct ItemListRevealOption: Equatable { let key: Int32 @@ -69,18 +69,18 @@ private final class ItemListRevealOptionNode: ASDisplayNode { override func didLoad() { super.didLoad() - /*if let url = frameworkBundle.url(forResource: "mute", withExtension: "json") { - let animView = LOTAnimationView(contentsOf: url) - animView.frame = CGRect(origin: CGPoint(), size: CGSize(width: 50.0, height: 50.0)) - self.animView = animView - self.view.addSubview(animView) - animView.loopAnimation = true - animView.logHierarchyKeypaths() - animView.setValue(UIColor.green, forKeypath: "Outlines.Group 1.Fill 1.Color", atFrame: 0) - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0, execute: { - animView.play() - }) - }*/ +// if let url = frameworkBundle.url(forResource: "anim_mute", withExtension: "json") { +// let animView = LOTAnimationView(contentsOf: url) +// animView.frame = CGRect(origin: CGPoint(), size: CGSize(width: 50.0, height: 50.0)) +// self.animView = animView +// self.view.addSubview(animView) +// animView.loopAnimation = true +// animView.logHierarchyKeypaths() +// animView.setValue(UIColor.green, forKeypath: "Outlines.Group 1.Fill 1.Color", atFrame: 0) +// DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0, execute: { +// animView.play() +// }) +// } } func updateLayout(baseSize: CGSize, alignment: ItemListRevealOptionAlignment, extendedWidth: CGFloat, transition: ContainedViewLayoutTransition) { diff --git a/TelegramUI/ItemListSecretChatKeyItem.swift b/TelegramUI/ItemListSecretChatKeyItem.swift index 547762bfba..ceaf5b0029 100644 --- a/TelegramUI/ItemListSecretChatKeyItem.swift +++ b/TelegramUI/ItemListSecretChatKeyItem.swift @@ -163,17 +163,15 @@ class ItemListSecretChatKeyItemNode: ListViewItemNode { let itemBackgroundColor: UIColor let itemSeparatorColor: UIColor - var leftInset: CGFloat = params.leftInset + var leftInset = 16.0 + params.leftInset switch item.style { case .plain: - leftInset += 35.0 itemBackgroundColor = item.theme.list.plainBackgroundColor itemSeparatorColor = item.theme.list.itemPlainSeparatorColor contentSize = CGSize(width: params.width, height: 44.0) insets = itemListNeighborsPlainInsets(neighbors) case .blocks: - leftInset += 16.0 itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor contentSize = CGSize(width: params.width, height: 44.0) diff --git a/TelegramUI/ItemListSwitchItem.swift b/TelegramUI/ItemListSwitchItem.swift index db3505fd48..a863f15620 100644 --- a/TelegramUI/ItemListSwitchItem.swift +++ b/TelegramUI/ItemListSwitchItem.swift @@ -216,12 +216,10 @@ class ItemListSwitchItemNode: ListViewItemNode { let _ = titleApply() - let leftInset: CGFloat + let leftInset = 16.0 + params.leftInset switch item.style { case .plain: - leftInset = 35.0 + params.leftInset - if strongSelf.backgroundNode.supernode != nil { strongSelf.backgroundNode.removeFromSupernode() } @@ -234,8 +232,6 @@ class ItemListSwitchItemNode: ListViewItemNode { strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight)) case .blocks: - leftInset = 16.0 + params.leftInset - if strongSelf.backgroundNode.supernode == nil { strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0) } diff --git a/TelegramUI/ItemListTextWithLabelItem.swift b/TelegramUI/ItemListTextWithLabelItem.swift index 88fb7bdca7..05633b88a2 100644 --- a/TelegramUI/ItemListTextWithLabelItem.swift +++ b/TelegramUI/ItemListTextWithLabelItem.swift @@ -6,6 +6,7 @@ import SwiftSignalKit enum ItemListTextWithLabelItemTextColor { case primary case accent + case highlighted } final class ItemListTextWithLabelItem: ListViewItem, ItemListItem { @@ -166,7 +167,7 @@ class ItemListTextWithLabelItemNode: ListViewItemNode { } let insets = itemListNeighborsPlainInsets(neighbors) - let leftInset: CGFloat = 35.0 + params.leftInset + let leftInset: CGFloat = 16.0 + params.leftInset let rightInset: CGFloat = 8.0 + params.rightInset let separatorHeight = UIScreenPixel @@ -184,6 +185,8 @@ class ItemListTextWithLabelItemNode: ListViewItemNode { labelColor = item.theme.list.itemPrimaryTextColor case .accent: labelColor = item.theme.list.itemAccentColor + case .highlighted: + labelColor = item.theme.list.itemHighlightedColor } let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.label, font: labelFont, textColor: labelColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftOffset - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) @@ -194,6 +197,8 @@ class ItemListTextWithLabelItemNode: ListViewItemNode { baseColor = item.theme.list.itemPrimaryTextColor case .accent: baseColor = item.theme.list.itemAccentColor + case .highlighted: + baseColor = item.theme.list.itemHighlightedColor } let string = stringWithAppliedEntities(item.text, entities: entities, baseColor: baseColor, linkColor: item.theme.list.itemAccentColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, fixedFont: textFixedFont) @@ -248,7 +253,7 @@ class ItemListTextWithLabelItemNode: ListViewItemNode { let style = ItemListStyle.plain switch style { case .plain: - leftInset = 35.0 + params.leftInset + leftOffset + leftInset = 16.0 + params.leftInset + leftOffset if strongSelf.backgroundNode.supernode != nil { strongSelf.backgroundNode.removeFromSupernode() diff --git a/TelegramUI/LanguageSelectionController.swift b/TelegramUI/LanguageSelectionController.swift index 8ec6bb15e0..96ba54486f 100644 --- a/TelegramUI/LanguageSelectionController.swift +++ b/TelegramUI/LanguageSelectionController.swift @@ -240,7 +240,7 @@ private final class InnerLanguageSelectionController: UIViewController, UITableV self.searchController.searchBar.barTintColor = self.presentationData.theme.chatList.backgroundColor self.searchController.searchBar.tintColor = self.presentationData.theme.rootController.navigationBar.accentTextColor self.searchController.searchBar.backgroundColor = self.presentationData.theme.chatList.backgroundColor - self.searchController.searchBar.setTextColor(self.presentationData.theme.chatList.titleColor) + self.searchController.searchBar.setTextColor(self.presentationData.theme.chatList.titleColor) let searchImage = generateImage(CGSize(width: 8.0, height: 28.0), rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) @@ -251,6 +251,14 @@ private final class InnerLanguageSelectionController: UIViewController, UITableV }) self.searchController.searchBar.setSearchFieldBackgroundImage(searchImage, for: []) self.searchController.searchBar.backgroundImage = UIImage() + + if let textFieldOfSearchBar = self.searchController.searchBar.value(forKey: "searchField") as? UITextField { + if #available(iOSApplicationExtension 11.0, *) { + textFieldOfSearchBar.textAlignment = .center + } + textFieldOfSearchBar.font = Font.regular(14.0) + textFieldOfSearchBar.keyboardAppearance = self.presentationData.theme.chatList.searchBarKeyboardColor == .light ? .default : .dark + } } func numberOfSections(in tableView: UITableView) -> Int { diff --git a/TelegramUI/LegacyCamera.swift b/TelegramUI/LegacyCamera.swift index f5894d5f2b..d846f147ef 100644 --- a/TelegramUI/LegacyCamera.swift +++ b/TelegramUI/LegacyCamera.swift @@ -6,7 +6,7 @@ import TelegramCore import Postbox import SwiftSignalKit -func presentedLegacyCamera(account: Account, peer: Peer, cameraView: TGAttachmentCameraView?, menuController: TGMenuSheetController?, parentController: ViewController, editingMedia: Bool, saveCapturedPhotos: Bool, sendMessagesWithSignals: @escaping ([Any]?) -> Void) { +func presentedLegacyCamera(account: Account, peer: Peer, cameraView: TGAttachmentCameraView?, menuController: TGMenuSheetController?, parentController: ViewController, editingMedia: Bool, saveCapturedPhotos: Bool, mediaGrouping: Bool, sendMessagesWithSignals: @escaping ([Any]?) -> Void) { let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme) legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .portrait, compactSize: .portrait) @@ -27,6 +27,8 @@ func presentedLegacyCamera(account: Account, peer: Peer, cameraView: TGAttachmen controller.isImportant = true controller.shouldStoreCapturedAssets = saveCapturedPhotos && !isSecretChat controller.allowCaptions = true + controller.allowCaptionEntities = true + controller.allowGrouping = mediaGrouping controller.inhibitDocumentCaptions = false controller.suggestionContext = legacySuggestionContext(account: account, peerId: peer.id) controller.recipientName = peer.displayTitle @@ -118,7 +120,7 @@ func presentedLegacyCamera(account: Account, peer: Peer, cameraView: TGAttachmen parentController.present(legacyController, in: .window(.root)) } -func presentedLegacyShortcutCamera(account: Account, saveCapturedMedia: Bool, saveEditedPhotos: Bool, parentController: ViewController) { +func presentedLegacyShortcutCamera(account: Account, saveCapturedMedia: Bool, saveEditedPhotos: Bool, mediaGrouping: Bool, parentController: ViewController) { let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme) legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .portrait, compactSize: .portrait) @@ -131,6 +133,8 @@ func presentedLegacyShortcutCamera(account: Account, saveCapturedMedia: Bool, sa controller.isImportant = true controller.shouldStoreCapturedAssets = saveCapturedMedia controller.allowCaptions = true + controller.allowCaptionEntities = true + controller.allowGrouping = mediaGrouping let screenSize = parentController.view.bounds.size let startFrame = CGRect(x: 0, y: screenSize.height, width: screenSize.width, height: screenSize.height) diff --git a/TelegramUI/LegacyChannelIntroController.swift b/TelegramUI/LegacyChannelIntroController.swift index 8e3e47ca3d..d74e872616 100644 --- a/TelegramUI/LegacyChannelIntroController.swift +++ b/TelegramUI/LegacyChannelIntroController.swift @@ -8,7 +8,11 @@ func legacyChannelIntroController(account: Account, theme: PresentationTheme, st let controller = LegacyController(presentation: .custom, theme: theme) controller.bind(controller: TGChannelIntroController(context: controller.context, getLocalizedString: { string in return strings.dict[string!] ?? string - }, theme: TGChannelIntroControllerTheme(backgroundColor: theme.list.plainBackgroundColor, primaryColor: theme.list.itemPrimaryTextColor, secondaryColor: theme.list.itemSecondaryTextColor, accentColor: theme.list.itemAccentColor, backArrowImage: NavigationBarTheme.generateBackArrowImage(color: theme.list.itemAccentColor), introImage: UIImage(bundleImageName: "Chat/Intro/ChannelIntro")), completion: { [weak controller] in + }, theme: TGChannelIntroControllerTheme(backgroundColor: theme.list.plainBackgroundColor, primaryColor: theme.list.itemPrimaryTextColor, secondaryColor: theme.list.itemSecondaryTextColor, accentColor: theme.list.itemAccentColor, backArrowImage: NavigationBarTheme.generateBackArrowImage(color: theme.list.itemAccentColor), introImage: UIImage(bundleImageName: "Chat/Intro/ChannelIntro")), dismiss: { [weak controller] in + if let navigationController = controller?.navigationController as? NavigationController { + _ = navigationController.popViewController(animated: true) + } + }, completion: { [weak controller] in if let navigationController = controller?.navigationController as? NavigationController { navigationController.replaceTopController(createChannelController(account: account), animated: true) } diff --git a/TelegramUI/LegacyLocationController.swift b/TelegramUI/LegacyLocationController.swift index 62868dd4c2..2e7c49d7f0 100644 --- a/TelegramUI/LegacyLocationController.swift +++ b/TelegramUI/LegacyLocationController.swift @@ -121,6 +121,47 @@ func legacyLocationController(message: Message, mapMedia: TelegramMediaMap, acco let legacyMessage = makeLegacyMessage(message) let controller: TGLocationViewController + + let updatedLocations = SSignal(generator: { subscriber in + let disposable = topPeerActiveLiveLocationMessages(viewTracker: account.viewTracker, accountPeerId: account.peerId, peerId: message.id.peerId).start(next: { (_, messages) in + var result: [Any] = [] + let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) + loop: for message in messages { + var liveBroadcastingTimeout: Int32 = 0 + + mediaLoop: for media in message.media { + if let map = media as? TelegramMediaMap, let timeout = map.liveBroadcastingTimeout { + liveBroadcastingTimeout = timeout + break mediaLoop + } + } + + let legacyMessage = makeLegacyMessage(message) + guard let legacyAuthor = message.author.flatMap(makeLegacyPeer) else { + continue loop + } + let remainingTime = max(0, message.timestamp + liveBroadcastingTimeout - currentTime) + if legacyMessage.locationAttachment?.period != 0 { + let hasOwnSession = message.localTags.contains(.OutgoingLiveLocation) + var isOwn = false + if !message.flags.contains(.Incoming) { + isOwn = true + } else if let peer = message.peers[message.id.peerId] as? TelegramChannel { + isOwn = peer.hasAdminRights(.canPostMessages) + } + + let liveLocation = TGLiveLocation(message: legacyMessage, peer: legacyAuthor, hasOwnSession: hasOwnSession, isOwnLocation: isOwn, isExpired: remainingTime == 0)! + result.append(liveLocation) + } + } + subscriber?.putNext(result) + }) + + return SBlockDisposable(block: { + disposable.dispose() + }) + })! + if let liveBroadcastingTimeout = mapMedia.liveBroadcastingTimeout { let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) let remainingTime = max(0, message.timestamp + liveBroadcastingTimeout - currentTime) @@ -129,57 +170,30 @@ func legacyLocationController(message: Message, mapMedia: TelegramMediaMap, acco controller = TGLocationViewController(context: legacyController.context, liveLocation: messageLiveLocation) - controller.remainingTimeForMessage = { message in - return legacyRemainingTime(message: message!) - } - controller.liveLocationStarted = { [weak legacyController] coordinate, period in - sendLiveLocation(coordinate, period) - legacyController?.dismiss() - } - controller.liveLocationStopped = { [weak legacyController] in - stopLiveLocation() - legacyController?.dismiss() - } if remainingTime == 0 { let freezeLocations: [Any] = [messageLiveLocation] controller.setLiveLocationsSignal(.single(freezeLocations)) } else { - let updatedLocations = SSignal(generator: { subscriber in - let disposable = topPeerActiveLiveLocationMessages(viewTracker: account.viewTracker, accountPeerId: account.peerId, peerId: message.id.peerId).start(next: { (_, messages) in - var result: [Any] = [] - let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) - loop: for message in messages { - let legacyMessage = makeLegacyMessage(message) - guard let legacyAuthor = message.author.flatMap(makeLegacyPeer) else { - continue loop - } - let remainingTime = max(0, message.timestamp + liveBroadcastingTimeout - currentTime) - if legacyMessage.locationAttachment?.period != 0 { - let hasOwnSession = message.localTags.contains(.OutgoingLiveLocation) - var isOwn = false - if !message.flags.contains(.Incoming) { - isOwn = true - } else if let peer = message.peers[message.id.peerId] as? TelegramChannel { - isOwn = peer.hasAdminRights(.canPostMessages) - } - - let liveLocation = TGLiveLocation(message: legacyMessage, peer: legacyAuthor, hasOwnSession: hasOwnSession, isOwnLocation: isOwn, isExpired: remainingTime == 0)! - result.append(liveLocation) - } - } - subscriber?.putNext(result) - }) - - return SBlockDisposable(block: { - disposable.dispose() - }) - })! controller.setLiveLocationsSignal(updatedLocations) } } else { controller = TGLocationViewController(context: legacyController.context, message: legacyMessage, peer: legacyAuthor)! controller.receivingPeer = message.peers[message.id.peerId].flatMap(makeLegacyPeer) + controller.setLiveLocationsSignal(updatedLocations) } + + controller.remainingTimeForMessage = { message in + return legacyRemainingTime(message: message!) + } + controller.liveLocationStarted = { [weak legacyController] coordinate, period in + sendLiveLocation(coordinate, period) + legacyController?.dismiss() + } + controller.liveLocationStopped = { [weak legacyController] in + stopLiveLocation() + legacyController?.dismiss() + } + let namespacesWithEnabledLiveLocation: Set = Set([ Namespaces.Peer.CloudChannel, Namespaces.Peer.CloudGroup, @@ -193,7 +207,7 @@ func legacyLocationController(message: Message, mapMedia: TelegramMediaMap, acco let listTheme = theme.list let searchTheme = theme.rootController.activeNavigationSearchBar - controller.pallete = TGLocationPallete(backgroundColor: listTheme.plainBackgroundColor, selectionColor: listTheme.itemHighlightedBackgroundColor, separatorColor: listTheme.itemPlainSeparatorColor, textColor: listTheme.itemPrimaryTextColor, secondaryTextColor: listTheme.itemSecondaryTextColor, accentColor: listTheme.itemAccentColor, destructiveColor: listTheme.itemDestructiveColor, locationColor: UIColor(rgb: 0x008df2), liveLocationColor: UIColor(rgb: 0xff6464), iconColor: listTheme.controlSecondaryColor, sectionHeaderBackgroundColor: theme.chatList.sectionHeaderFillColor, sectionHeaderTextColor: theme.chatList.sectionHeaderTextColor, searchBarPallete: TGSearchBarPallete(dark: theme.overallDarkAppearance, backgroundColor: searchTheme.backgroundColor, highContrastBackgroundColor: searchTheme.backgroundColor, textColor: searchTheme.inputTextColor, placeholderColor: searchTheme.inputPlaceholderTextColor, clearIcon: generateClearIcon(color: theme.rootController.activeNavigationSearchBar.inputClearButtonColor), barBackgroundColor: searchTheme.backgroundColor, barSeparatorColor: searchTheme.separatorColor, plainBackgroundColor: searchTheme.backgroundColor, accentColor: searchTheme.accentColor, accentContrastColor: searchTheme.accentColor, menuBackgroundColor: searchTheme.backgroundColor, segmentedControlBackgroundImage: nil, segmentedControlSelectedImage: nil, segmentedControlHighlightedImage: nil, segmentedControlDividerImage: nil), avatarPlaceholder: nil) + controller.pallete = TGLocationPallete(backgroundColor: listTheme.plainBackgroundColor, selectionColor: listTheme.itemHighlightedBackgroundColor, separatorColor: listTheme.itemPlainSeparatorColor, textColor: listTheme.itemPrimaryTextColor, secondaryTextColor: listTheme.itemSecondaryTextColor, accentColor: listTheme.itemAccentColor, destructiveColor: listTheme.itemDestructiveColor, locationColor: UIColor(rgb: 0x008df2), liveLocationColor: UIColor(rgb: 0xff6464), iconColor: searchTheme.backgroundColor, sectionHeaderBackgroundColor: theme.chatList.sectionHeaderFillColor, sectionHeaderTextColor: theme.chatList.sectionHeaderTextColor, searchBarPallete: TGSearchBarPallete(dark: theme.overallDarkAppearance, backgroundColor: searchTheme.backgroundColor, highContrastBackgroundColor: searchTheme.backgroundColor, textColor: searchTheme.inputTextColor, placeholderColor: searchTheme.inputPlaceholderTextColor, clearIcon: generateClearIcon(color: theme.rootController.activeNavigationSearchBar.inputClearButtonColor), barBackgroundColor: searchTheme.backgroundColor, barSeparatorColor: searchTheme.separatorColor, plainBackgroundColor: searchTheme.backgroundColor, accentColor: searchTheme.accentColor, accentContrastColor: searchTheme.backgroundColor, menuBackgroundColor: searchTheme.backgroundColor, segmentedControlBackgroundImage: nil, segmentedControlSelectedImage: nil, segmentedControlHighlightedImage: nil, segmentedControlDividerImage: nil), avatarPlaceholder: nil) controller.modalMode = true let navigationController = TGNavigationController(controllers: [controller])! diff --git a/TelegramUI/LegacyLocationPicker.swift b/TelegramUI/LegacyLocationPicker.swift index 0f4ad1e9da..55a2d3afe8 100644 --- a/TelegramUI/LegacyLocationPicker.swift +++ b/TelegramUI/LegacyLocationPicker.swift @@ -16,7 +16,7 @@ func legacyLocationPickerController(account: Account, selfPeer: Peer, peer: Peer controller.receivingPeer = makeLegacyPeer(peer) let listTheme = theme.list let searchTheme = theme.rootController.activeNavigationSearchBar - controller.pallete = TGLocationPallete(backgroundColor: listTheme.plainBackgroundColor, selectionColor: listTheme.itemHighlightedBackgroundColor, separatorColor: listTheme.itemPlainSeparatorColor, textColor: listTheme.itemPrimaryTextColor, secondaryTextColor: listTheme.itemSecondaryTextColor, accentColor: listTheme.itemAccentColor, destructiveColor: listTheme.itemDestructiveColor, locationColor: UIColor(rgb: 0x008df2), liveLocationColor: UIColor(rgb: 0xff6464), iconColor: listTheme.controlSecondaryColor, sectionHeaderBackgroundColor: theme.chatList.sectionHeaderFillColor, sectionHeaderTextColor: theme.chatList.sectionHeaderTextColor, searchBarPallete: TGSearchBarPallete(dark: theme.overallDarkAppearance, backgroundColor: searchTheme.backgroundColor, highContrastBackgroundColor: searchTheme.backgroundColor, textColor: searchTheme.inputTextColor, placeholderColor: searchTheme.inputPlaceholderTextColor, clearIcon: generateClearIcon(color: theme.rootController.activeNavigationSearchBar.inputClearButtonColor), barBackgroundColor: searchTheme.backgroundColor, barSeparatorColor: searchTheme.separatorColor, plainBackgroundColor: searchTheme.backgroundColor, accentColor: searchTheme.accentColor, accentContrastColor: searchTheme.accentColor, menuBackgroundColor: searchTheme.backgroundColor, segmentedControlBackgroundImage: nil, segmentedControlSelectedImage: nil, segmentedControlHighlightedImage: nil, segmentedControlDividerImage: nil), avatarPlaceholder: nil) + controller.pallete = TGLocationPallete(backgroundColor: listTheme.plainBackgroundColor, selectionColor: listTheme.itemHighlightedBackgroundColor, separatorColor: listTheme.itemPlainSeparatorColor, textColor: listTheme.itemPrimaryTextColor, secondaryTextColor: listTheme.itemSecondaryTextColor, accentColor: listTheme.itemAccentColor, destructiveColor: listTheme.itemDestructiveColor, locationColor: UIColor(rgb: 0x008df2), liveLocationColor: UIColor(rgb: 0xff6464), iconColor: searchTheme.backgroundColor, sectionHeaderBackgroundColor: theme.chatList.sectionHeaderFillColor, sectionHeaderTextColor: theme.chatList.sectionHeaderTextColor, searchBarPallete: TGSearchBarPallete(dark: theme.overallDarkAppearance, backgroundColor: searchTheme.inputFillColor, highContrastBackgroundColor: searchTheme.inputFillColor, textColor: searchTheme.inputTextColor, placeholderColor: searchTheme.inputPlaceholderTextColor, clearIcon: generateClearIcon(color: theme.rootController.activeNavigationSearchBar.inputClearButtonColor), barBackgroundColor: searchTheme.backgroundColor, barSeparatorColor: searchTheme.separatorColor, plainBackgroundColor: searchTheme.backgroundColor, accentColor: searchTheme.accentColor, accentContrastColor: searchTheme.backgroundColor, menuBackgroundColor: searchTheme.backgroundColor, segmentedControlBackgroundImage: nil, segmentedControlSelectedImage: nil, segmentedControlHighlightedImage: nil, segmentedControlDividerImage: nil), avatarPlaceholder: nil) let namespacesWithEnabledLiveLocation: Set = Set([ Namespaces.Peer.CloudChannel, Namespaces.Peer.CloudGroup, diff --git a/TelegramUI/MediaInputPaneTrendingItem.swift b/TelegramUI/MediaInputPaneTrendingItem.swift index 2a1aa87b50..23bf430b48 100644 --- a/TelegramUI/MediaInputPaneTrendingItem.swift +++ b/TelegramUI/MediaInputPaneTrendingItem.swift @@ -189,7 +189,7 @@ class MediaInputPaneTrendingItemNode: ListViewItemNode { let (descriptionLayout, descriptionApply) = makeDescriptionLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.strings.StickerPack_StickerCount(item.info.count), font: statusFont, textColor: item.theme.chat.inputMediaPanel.stickersSectionTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - leftInset - rightInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - let contentSize: CGSize = CGSize(width: params.width, height: 116.0) + let contentSize: CGSize = CGSize(width: params.width, height: 120.0) let insets: UIEdgeInsets = UIEdgeInsets(top: 8.0, left: 0.0, bottom: 0.0, right: 0.0) let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) @@ -244,15 +244,13 @@ class MediaInputPaneTrendingItemNode: ListViewItemNode { strongSelf.unreadNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX + 2.0, y: titleFrame.minY + 7.0), size: image.size) } - var offset: CGFloat = params.leftInset + leftInset - let availableWidth = params.width - params.leftInset - params.rightInset - leftInset * 2.0 - var itemSide: CGFloat = floor((availableWidth) / 5.0) - var itemSpacing: CGFloat = 0.0 - if itemSide >= 60.0 { - itemSpacing = max(0.0, min(6.0, itemSide - 60.0)) - } - itemSide = min(itemSide, 60.0) + let sideInset: CGFloat = 2.0 + let availableWidth = params.width - params.leftInset - params.rightInset - sideInset * 2.0 + var itemSide: CGFloat = floor(availableWidth / 5.0) + itemSide = min(itemSide, 75.0) let itemSize = CGSize(width: itemSide, height: itemSide) + var offset = sideInset + let itemSpacing = (max(0, availableWidth - 5.0 * itemSide - sideInset * 2.0)) / 4.0 for i in 0 ..< topItems.count { let file = topItems[i].file @@ -274,7 +272,7 @@ class MediaInputPaneTrendingItemNode: ListViewItemNode { let imageSize = dimensions.aspectFitted(itemSize) node.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))() node.frame = CGRect(origin: CGPoint(x: offset, y: 48.0), size: imageSize) - offset += imageSize.width + itemSpacing + offset += itemSize.width + itemSpacing } } diff --git a/TelegramUI/OpenInAppIconResources.swift b/TelegramUI/OpenInAppIconResources.swift index 78fe322d28..8000415af8 100644 --- a/TelegramUI/OpenInAppIconResources.swift +++ b/TelegramUI/OpenInAppIconResources.swift @@ -3,7 +3,7 @@ import TelegramCore import SwiftSignalKit import Postbox -func fetchOpenInAppIconResource(account: Account, resource: OpenInAppIconResource) -> Signal { +func fetchOpenInAppIconResource(resource: OpenInAppIconResource) -> Signal { return Signal { subscriber in subscriber.putNext(.reset) diff --git a/TelegramUI/OpenUrl.swift b/TelegramUI/OpenUrl.swift index d02a62a5c6..e0fa7fc824 100644 --- a/TelegramUI/OpenUrl.swift +++ b/TelegramUI/OpenUrl.swift @@ -6,7 +6,7 @@ import Postbox import SwiftSignalKit public func openExternalUrl(account: Account, url: String, presentationData: PresentationData, applicationContext: TelegramApplicationContext, navigationController: NavigationController?, dismissInput: @escaping () -> Void) { - if url.lowercased().hasPrefix("tel:") { + if url.lowercased().hasPrefix("tel:") || url.lowercased().hasPrefix("calshow:") { applicationContext.applicationBindings.openUrl(url) return } diff --git a/TelegramUI/OverlayPlayerControllerNode.swift b/TelegramUI/OverlayPlayerControllerNode.swift index 8c9320911a..aeb326b818 100644 --- a/TelegramUI/OverlayPlayerControllerNode.swift +++ b/TelegramUI/OverlayPlayerControllerNode.swift @@ -194,6 +194,10 @@ final class OverlayPlayerControllerNode: ViewControllerTracingNode, UIGestureRec insets.right = layout.safeInsets.right insets.bottom = layout.intrinsicInsets.bottom + if layout.size.width > layout.size.height && self.controlsNode.isExpanded { + self.controlsNode.isExpanded = false + } + let maxHeight = layout.size.height - layoutTopInset - floor(56.0 * 0.5) let controlsHeight = OverlayPlayerControlsNode.heightForLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: maxHeight, isExpanded: self.controlsNode.isExpanded) @@ -259,9 +263,9 @@ final class OverlayPlayerControllerNode: ViewControllerTracingNode, UIGestureRec } let result = super.hitTest(point, with: event) if self.controlsNode.frame.contains(point) { - if result == self.historyNode.view { - return self.view - } +// if result == self.historyNode.view { +// return self.view +// } } return result } diff --git a/TelegramUI/OverlayPlayerControlsNode.swift b/TelegramUI/OverlayPlayerControlsNode.swift index e4de319cef..e82bb3c08d 100644 --- a/TelegramUI/OverlayPlayerControlsNode.swift +++ b/TelegramUI/OverlayPlayerControlsNode.swift @@ -81,7 +81,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode { let separatorNode: ASDisplayNode - private(set) var isExpanded = false + var isExpanded = false var updateIsExpanded: (() -> Void)? var requestCollapse: (() -> Void)? @@ -319,14 +319,14 @@ final class OverlayPlayerControlsNode: ASDisplayNode { let (titleString, descriptionString) = stringsForDisplayData(self.displayData, theme: self.theme) let makeTitleLayout = TextNode.asyncLayout(self.titleNode) - let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - sideInset * 2.0 - infoLabelsLeftInset - infoLabelsRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) + let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - sideInset * 2.0 - leftInset - rightInset - infoLabelsLeftInset - infoLabelsRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) let makeDescriptionLayout = TextNode.asyncLayout(self.descriptionNode) - let (descriptionLayout, descriptionApply) = makeDescriptionLayout(TextNodeLayoutArguments(attributedString: descriptionString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - sideInset * 2.0 - infoLabelsLeftInset - infoLabelsRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) + let (descriptionLayout, descriptionApply) = makeDescriptionLayout(TextNodeLayoutArguments(attributedString: descriptionString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - sideInset * 2.0 - leftInset - rightInset - infoLabelsLeftInset - infoLabelsRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) - transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: self.isExpanded ? floor((width - titleLayout.size.width) / 2.0) : (sideInset + infoLabelsLeftInset), y: infoVerticalOrigin + 1.0), size: titleLayout.size)) + transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: self.isExpanded ? floor((width - titleLayout.size.width) / 2.0) : (leftInset + sideInset + infoLabelsLeftInset), y: infoVerticalOrigin + 1.0), size: titleLayout.size)) let _ = titleApply() - transition.updateFrame(node: self.descriptionNode, frame: CGRect(origin: CGPoint(x: self.isExpanded ? floor((width - descriptionLayout.size.width) / 2.0) : (sideInset + infoLabelsLeftInset), y: infoVerticalOrigin + 27.0), size: descriptionLayout.size)) + transition.updateFrame(node: self.descriptionNode, frame: CGRect(origin: CGPoint(x: self.isExpanded ? floor((width - descriptionLayout.size.width) / 2.0) : (leftInset + sideInset + infoLabelsLeftInset), y: infoVerticalOrigin + 27.0), size: descriptionLayout.size)) let _ = descriptionApply() var albumArt: SharedMediaPlaybackAlbumArt? @@ -361,6 +361,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode { func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat { self.validLayout = (width, leftInset, rightInset, maxHeight) + let panelHeight = OverlayPlayerControlsNode.heightForLayout(width: width, leftInset: leftInset, rightInset: rightInset, maxHeight: maxHeight, isExpanded: self.isExpanded) @@ -381,7 +382,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode { let makeAlbumArtLayout = self.albumArtNode.asyncLayout() let applyAlbumArt = makeAlbumArtLayout(TransformImageArguments(corners: ImageCorners(radius: 4.0), imageSize: albumArtSize, boundingSize: albumArtSize, intrinsicInsets: UIEdgeInsets())) applyAlbumArt() - let albumArtFrame = CGRect(origin: CGPoint(x: sideInset, y: infoVerticalOrigin - 1.0), size: albumArtSize) + let albumArtFrame = CGRect(origin: CGPoint(x: leftInset + sideInset, y: infoVerticalOrigin - 1.0), size: albumArtSize) let previousAlbumArtNodeFrame = self.albumArtNode.frame transition.updateFrame(node: self.albumArtNode, frame: albumArtFrame) @@ -453,14 +454,14 @@ final class OverlayPlayerControlsNode: ASDisplayNode { let scrubberVerticalOrigin: CGFloat = infoVerticalOrigin + 64.0 - transition.updateFrame(node: self.scrubberNode, frame: CGRect(origin: CGPoint(x: sideInset, y: scrubberVerticalOrigin - 8.0), size: CGSize(width: width - sideInset * 2.0, height: 10.0 + 8.0 * 2.0))) - transition.updateFrame(node: self.leftDurationLabel, frame: CGRect(origin: CGPoint(x: sideInset, y: scrubberVerticalOrigin + 12.0), size: CGSize(width: 40.0, height: 20.0))) - transition.updateFrame(node: self.rightDurationLabel, frame: CGRect(origin: CGPoint(x: width - sideInset - 40.0, y: scrubberVerticalOrigin + 12.0), size: CGSize(width: 40.0, height: 20.0))) + transition.updateFrame(node: self.scrubberNode, frame: CGRect(origin: CGPoint(x: leftInset + sideInset, y: scrubberVerticalOrigin - 8.0), size: CGSize(width: width - sideInset * 2.0 - leftInset - rightInset, height: 10.0 + 8.0 * 2.0))) + transition.updateFrame(node: self.leftDurationLabel, frame: CGRect(origin: CGPoint(x: leftInset + sideInset, y: scrubberVerticalOrigin + 12.0), size: CGSize(width: 40.0, height: 20.0))) + transition.updateFrame(node: self.rightDurationLabel, frame: CGRect(origin: CGPoint(x: width - sideInset - rightInset - 40.0, y: scrubberVerticalOrigin + 12.0), size: CGSize(width: 40.0, height: 20.0))) transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -8.0), size: CGSize(width: width, height: panelHeight + 8.0))) let buttonSize = CGSize(width: 64.0, height: 64.0) - let buttonsWidth = width - leftInset - rightInset - sideButtonsInset * 2.0 + let buttonsWidth = min(width - leftInset - rightInset - sideButtonsInset * 2.0, 320.0) let buttonsRect = CGRect(origin: CGPoint(x: floor((width - buttonsWidth) / 2.0), y: scrubberVerticalOrigin + 36.0), size: CGSize(width: buttonsWidth, height: buttonSize.height)) transition.updateFrame(node: self.orderButton, frame: CGRect(origin: CGPoint(x: leftInset + sideInset - 22.0, y: buttonsRect.minY), size: buttonSize)) @@ -540,6 +541,12 @@ final class OverlayPlayerControlsNode: ASDisplayNode { @objc func albumArtTap(_ recognizer: UITapGestureRecognizer) { if case .ended = recognizer.state { + if let supernode = self.supernode { + let bounds = supernode.bounds + if bounds.width > bounds.height { + return + } + } self.isExpanded = !self.isExpanded self.updateIsExpanded?() } diff --git a/TelegramUI/PresentationTheme.swift b/TelegramUI/PresentationTheme.swift index b6f5c53ce1..22ae12e757 100644 --- a/TelegramUI/PresentationTheme.swift +++ b/TelegramUI/PresentationTheme.swift @@ -274,6 +274,7 @@ public final class PresentationThemeList { public let itemSecondaryTextColor: UIColor public let itemDisabledTextColor: UIColor public let itemAccentColor: UIColor + public let itemHighlightedColor: UIColor public let itemDestructiveColor: UIColor public let itemPlaceholderTextColor: UIColor public let itemBlocksBackgroundColor: UIColor @@ -292,13 +293,14 @@ public final class PresentationThemeList { public let controlSecondaryColor: UIColor public let freeInputField: PresentationInputFieldTheme - public init(blocksBackgroundColor: UIColor, plainBackgroundColor: UIColor, itemPrimaryTextColor: UIColor, itemSecondaryTextColor: UIColor, itemDisabledTextColor: UIColor, itemAccentColor: UIColor, itemDestructiveColor: UIColor, itemPlaceholderTextColor: UIColor, itemBlocksBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, itemBlocksSeparatorColor: UIColor, itemPlainSeparatorColor: UIColor, disclosureArrowColor: UIColor, sectionHeaderTextColor: UIColor, freeTextColor: UIColor, freeTextErrorColor: UIColor, freeTextSuccessColor: UIColor, freeMonoIcon: UIColor, itemSwitchColors: PresentationThemeSwitch, itemDisclosureActions: PresentationThemeItemDisclosureActions, itemCheckColors: PresentationThemeCheck, controlSecondaryColor: UIColor, freeInputField: PresentationInputFieldTheme) { + public init(blocksBackgroundColor: UIColor, plainBackgroundColor: UIColor, itemPrimaryTextColor: UIColor, itemSecondaryTextColor: UIColor, itemDisabledTextColor: UIColor, itemAccentColor: UIColor, itemHighlightedColor: UIColor, itemDestructiveColor: UIColor, itemPlaceholderTextColor: UIColor, itemBlocksBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, itemBlocksSeparatorColor: UIColor, itemPlainSeparatorColor: UIColor, disclosureArrowColor: UIColor, sectionHeaderTextColor: UIColor, freeTextColor: UIColor, freeTextErrorColor: UIColor, freeTextSuccessColor: UIColor, freeMonoIcon: UIColor, itemSwitchColors: PresentationThemeSwitch, itemDisclosureActions: PresentationThemeItemDisclosureActions, itemCheckColors: PresentationThemeCheck, controlSecondaryColor: UIColor, freeInputField: PresentationInputFieldTheme) { self.blocksBackgroundColor = blocksBackgroundColor self.plainBackgroundColor = plainBackgroundColor self.itemPrimaryTextColor = itemPrimaryTextColor self.itemSecondaryTextColor = itemSecondaryTextColor self.itemDisabledTextColor = itemDisabledTextColor self.itemAccentColor = itemAccentColor + self.itemHighlightedColor = itemHighlightedColor self.itemDestructiveColor = itemDestructiveColor self.itemPlaceholderTextColor = itemPlaceholderTextColor self.itemBlocksBackgroundColor = itemBlocksBackgroundColor diff --git a/TelegramUI/Resources/Animations/anim_delete.json b/TelegramUI/Resources/Animations/anim_delete.json new file mode 100644 index 0000000000..23b20fd472 --- /dev/null +++ b/TelegramUI/Resources/Animations/anim_delete.json @@ -0,0 +1 @@ +{"v":"5.1.2","fr":60,"ip":0,"op":3600,"w":228,"h":228,"nm":"delete","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"bin2 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[114,94,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.872,0.872,-0.667]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p872_0p333_0","0p833_0p872_0p333_0","0p833_-0p667_0p333_0"],"t":0,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.426,0.426,0.833]},"n":["0p667_1_0p167_0p426","0p667_1_0p167_0p426","0p667_1_0p167_0p833"],"t":10,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":15,"s":[115,115,100],"e":[100,100,100]},{"t":25}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-3.112,0],[0,0],[-0.269,3.1],[0,0]],"o":[[0,0],[0.269,3.1],[0,0],[3.113,0],[0,0],[0,0]],"v":[[-27,-34.5],[-21.476,29.02],[-15.499,34.5],[15.499,34.5],[21.476,29.02],[27,-34.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,1.057],[-1.884,32.041],[-1.107,0],[0,-1.057],[1.885,-32.041],[1.107,0]],"o":[[0,-0.038],[0.065,-1.105],[1.057,0],[0,0.038],[-0.065,1.105],[-1.058,0]],"v":[[8.586,23.086],[11.413,-25.032],[13.5,-27],[15.414,-25.086],[12.587,23.032],[10.5,25]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,1.105],[0,0],[-1.105,0],[0,-1.105],[0,0],[1.105,0]],"o":[[0,0],[0,-1.105],[1.105,0],[0,0],[0,1.105],[-1.105,0]],"v":[[-2,23],[-2,-25],[0,-27],[2,-25],[2,23],[0,25]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0.065,1.105],[0,0],[-1.057,0],[-0.066,-1.105],[0,0],[1.057,0]],"o":[[0,0],[-0.004,-1.17],[1.107,0],[0,0],[0.004,1.17],[-1.107,0]],"v":[[-12.587,23.032],[-15.411,-24.973],[-13.5,-27],[-11.412,-25.032],[-8.589,22.973],[-10.5,25]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[256,256.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":6,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"bin1 Outlines","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[45],"e":[0]},{"t":15}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[270,180,0],"e":[256,211.923,0],"to":[-2.33333325386047,5.32055473327637,0],"ti":[2.33333325386047,-5.32055473327637,0]},{"t":15}],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[100,100,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":10,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":15,"s":[115,115,100],"e":[100,100,100]},{"t":25}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.542,-0.903],[0,0],[0,0],[0,-3.314],[0,0],[3.314,0],[0,0],[0,0],[1.054,0]],"o":[[-1.054,0],[0,0],[0,0],[-3.314,0],[0,0],[0,-3.314],[0,0],[0,0],[-0.542,-0.903],[0,0]],"v":[[-7.301,-6],[-9.874,-4.544],[-12.6,0],[-24,0],[-30,6],[30,6],[24,0],[12.6,0],[9.874,-4.544],[7.301,-6]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[256,256],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-130,"op":3600,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TelegramUI/Resources/Animations/anim_group.json b/TelegramUI/Resources/Animations/anim_group.json new file mode 100644 index 0000000000..cc5a0437e1 --- /dev/null +++ b/TelegramUI/Resources/Animations/anim_group.json @@ -0,0 +1 @@ +{"v":"5.1.7","fr":60,"ip":0,"op":32,"w":228,"h":228,"nm":"group","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Oval 2 Copy 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[135.5,110.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":6,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":16,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":21,"s":[115,115,100],"e":[100,100,100]},{"t":31}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[33,33],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval 2 Copy 2","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":32,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Oval 2 Copy 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[93.5,110.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":4,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":14,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":19,"s":[115,115,100],"e":[100,100,100]},{"t":29}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[33,33],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval 2 Copy 3","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":32,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Oval 2 Copy","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[135.5,68.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":2,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":12,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":17,"s":[115,115,100],"e":[100,100,100]},{"t":27}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[33,33],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval 2 Copy","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":32,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Oval 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[93.5,68.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":10,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":15,"s":[115,115,100],"e":[100,100,100]},{"t":25}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[33,33],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval 2","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":32,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TelegramUI/Resources/mute.json b/TelegramUI/Resources/Animations/anim_mute.json similarity index 100% rename from TelegramUI/Resources/mute.json rename to TelegramUI/Resources/Animations/anim_mute.json diff --git a/TelegramUI/Resources/Animations/anim_pin.json b/TelegramUI/Resources/Animations/anim_pin.json new file mode 100644 index 0000000000..adb1491446 --- /dev/null +++ b/TelegramUI/Resources/Animations/anim_pin.json @@ -0,0 +1 @@ +{"v":"5.1.2","fr":60,"ip":0,"op":3600,"w":228,"h":228,"nm":"pinchat","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"pin Outlines","sr":1,"ks":{"o":{"a":0,"k":99,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[113.656,86.516,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.872,0.872,-10.015]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p872_0p333_0","0p833_0p872_0p333_0","0p833_-10p015_0p333_0"],"t":0,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.426,0.426,5.508]},"n":["0p667_1_0p167_0p426","0p667_1_0p167_0p426","0p667_1_0p167_5p508"],"t":10,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":15,"s":[115,115,100],"e":[100,100,100]},{"t":24}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.682,-2.385],[0,0],[7.227,-5.009],[0.494,-0.402],[0.078,-0.079],[-1.265,-1.266],[0,0],[-0.087,-0.07],[-1.129,1.388],[-0.211,0.297],[2.361,8.281],[0,0],[3.76,3.76],[0,0],[2.035,0]],"o":[[0,0],[-8.176,-2.331],[-0.37,0.258],[-0.086,0.07],[-1.265,1.265],[0,0],[0.079,0.078],[1.388,1.129],[0.312,-0.384],[5.172,-7.273],[0,0],[4.348,-3.067],[0,0],[-1.701,-1.701],[-2.465,0]],"v":[[10.943,-36.491],[-1.24,-19.219],[-25.643,-15.202],[-26.94,-14.213],[-27.187,-13.99],[-27.187,-9.408],[8.801,26.579],[9.049,26.802],[13.607,26.332],[14.391,25.311],[18.607,0.628],[35.879,-11.556],[36.955,-23.925],[23.313,-37.567],[17.514,-40.1]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-40.714,40.1],[-7.985,15.793],[-16.406,7.372]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[256.714,257.1],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TelegramUI/Resources/Animations/anim_read.json b/TelegramUI/Resources/Animations/anim_read.json new file mode 100644 index 0000000000..de017a73ed --- /dev/null +++ b/TelegramUI/Resources/Animations/anim_read.json @@ -0,0 +1 @@ +{"v":"4.5.6","fr":60,"ip":0,"op":30,"w":228,"h":228,"ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Combined Shape","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[114,89.499,0]},"a":{"a":0,"k":[40,38.499,0]},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,0.667]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p667_1_0p167_0p167","0p667_1_0p167_0p167","0p667_0p667_0p167_0p167"],"t":0,"s":[0,0,100],"e":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,0.667]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_0p667_0p333_0p333"],"t":15,"s":[110,110,100],"e":[100,100,100]},{"t":20}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.39,0],[0,19.29],[22.09,0],[0,-19.28],[-9.1,-6.4],[2.59,-3.82],[-1.62,-0.65],[-4.27,2.3],[-1.31,-0.29]],"o":[[22.09,0],[0,-19.28],[-22.09,0],[0,11],[1.17,0.82],[-2.6,3.82],[1,0.4],[6.1,-3.28],[3.14,0.69]],"v":[[40,69.85],[80,34.92],[40,0],[0,34.92],[14.45,61.34],[14.1,70.53],[9.89,76.75],[21.07,75.05],[30.18,68.79]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"mn":"ADBE Vector Group"}],"ip":0,"op":30,"st":0,"bm":0,"sr":1}]} \ No newline at end of file diff --git a/TelegramUI/Resources/Animations/anim_ungroup.json b/TelegramUI/Resources/Animations/anim_ungroup.json new file mode 100644 index 0000000000..0ad2298e46 --- /dev/null +++ b/TelegramUI/Resources/Animations/anim_ungroup.json @@ -0,0 +1 @@ +{"v":"5.1.7","fr":60,"ip":0,"op":32,"w":228,"h":228,"nm":"ungroup","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"un Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[114.75,89.312,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.872,0.872,-11.778]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p872_0p333_0","0p833_0p872_0p333_0","0p833_-11p778_0p333_0"],"t":0,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.426,0.426,6.389]},"n":["0p667_1_0p167_0p426","0p667_1_0p167_0p426","0p667_1_0p167_6p389"],"t":10,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":15,"s":[115,115,100],"e":[100,100,100]},{"t":24}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":5,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-34,-34],[-33.992,-34]],"c":false}],"e":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-34,-34],[34,34]],"c":false}]},{"t":15}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"ix":5},"lc":2,"lj":1,"ml":10,"nm":"Stroke 2","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"st","c":{"a":0,"k":[0.097999999102,0.57599995931,0.980000035903,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":15,"ix":5},"lc":2,"lj":1,"ml":10,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[256,256],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":32,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Oval 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[93.5,68.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":10,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":15,"s":[115,115,100],"e":[100,100,100]},{"t":25}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[33,33],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval 2","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":32,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Oval 2 Copy","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[135.5,68.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":2,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":12,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":17,"s":[115,115,100],"e":[100,100,100]},{"t":27}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[33,33],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval 2 Copy","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":32,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Oval 2 Copy 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[93.5,110.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":4,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":14,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":19,"s":[115,115,100],"e":[100,100,100]},{"t":29}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[33,33],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval 2 Copy 3","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":32,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Oval 2 Copy 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[135.5,110.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":6,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":16,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":21,"s":[115,115,100],"e":[100,100,100]},{"t":31}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[33,33],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval 2 Copy 2","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":32,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TelegramUI/Resources/Animations/anim_unmute.json b/TelegramUI/Resources/Animations/anim_unmute.json new file mode 100644 index 0000000000..f1059e9a2d --- /dev/null +++ b/TelegramUI/Resources/Animations/anim_unmute.json @@ -0,0 +1 @@ +{"v":"5.1.2","fr":60,"ip":0,"op":3600,"w":228,"h":228,"nm":"unmute","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"vol1 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[120,90,0],"e":[131,90,0],"to":[1.83333337306976,0,0],"ti":[-1.83333337306976,0,0]},{"t":10}],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.872,0.872,-11.778]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p872_0p333_0","0p833_0p872_0p333_0","0p833_-11p778_0p333_0"],"t":0,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.426,0.426,6.389]},"n":["0p667_1_0p167_0p426","0p667_1_0p167_0p426","0p667_1_0p167_6p389"],"t":10,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":15,"s":[115,115,100],"e":[100,100,100]},{"t":25}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.577,-0.531],[0.016,-0.789],[0,0],[-0.516,-0.561],[0,-5.477],[4.174,-4.561],[0.014,-0.704],[0,0],[-0.631,-0.578],[-1.119,1.223],[0,7.023],[5.163,5.605],[0.809,0]],"o":[[-0.627,0.576],[0,0],[0.015,0.706],[4.17,4.526],[0,5.479],[-0.513,0.56],[0,0],[0.016,0.793],[1.222,1.118],[5.16,-5.636],[0,-7.025],[-0.592,-0.641],[-0.726,0]],"v":[[-5.533,-19.371],[-6.5,-17.224],[-6.5,-17.104],[-5.707,-15.133],[0.5,-0.19],[-5.713,14.81],[-6.5,16.777],[-6.5,16.892],[-5.526,19.048],[-1.287,18.859],[6.5,-0.19],[-1.293,-19.198],[-3.501,-20.165]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[255.5,256.165],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"vol2 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":2,"s":[120,90,0],"e":[146,90,0],"to":[4.33333349227905,0,0],"ti":[-4.33333349227905,0,0]},{"t":12}],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.872,0.872,-11.778]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p872_0p333_0","0p833_0p872_0p333_0","0p833_-11p778_0p333_0"],"t":2,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.426,0.426,6.389]},"n":["0p667_1_0p167_0p426","0p667_1_0p167_0p426","0p667_1_0p167_6p389"],"t":12,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":17,"s":[115,115,100],"e":[100,100,100]},{"t":27}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.56,-0.468],[-1.06,-1.273],[0,-8.078],[6.916,-8.351],[-1.276,-1.057],[-1.057,1.275],[0,9.591],[7.755,9.312],[0.861,0]],"o":[[-1.274,1.06],[6.912,8.299],[0,8.082],[-1.057,1.276],[1.276,1.056],[7.751,-9.362],[0,-9.592],[-0.593,-0.713],[-0.675,0]],"v":[[-7.235,-28.988],[-7.622,-24.763],[2.684,-0.221],[-7.627,24.404],[-7.229,28.628],[-3.005,28.23],[8.684,-0.221],[-3.011,-28.603],[-5.319,-29.684]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[255.316,256.684],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"vol3 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":4,"s":[120,89.062,0],"e":[162,89.062,0],"to":[7,0,0],"ti":[-7,0,0]},{"t":14}],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.872,0.872,-11.778]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p872_0p333_0","0p833_0p872_0p333_0","0p833_-11p778_0p333_0"],"t":4,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.426,0.426,6.389]},"n":["0p667_1_0p167_0p426","0p667_1_0p167_0p426","0p667_1_0p167_6p389"],"t":14,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":19,"s":[115,115,100],"e":[100,100,100]},{"t":29}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.563,-0.475],[-1.067,-1.267],[0,-12.342],[9.568,-11.435],[-1.27,-1.063],[-0.665,-0.01],[0,0],[-0.582,0.697],[0,13.826],[10.437,12.396],[0.855,0]],"o":[[-1.268,1.066],[9.564,11.36],[0,12.345],[-1.063,1.271],[0.549,0.459],[0,0],[0.842,-0.013],[10.432,-12.468],[0,-13.827],[-0.593,-0.705],[-0.683,0]],"v":[[-9.25,-39.794],[-9.613,-35.568],[4.682,-0.056],[-9.619,35.575],[-9.243,39.801],[-7.364,40.5],[-7.274,40.5],[-5.017,39.425],[10.682,-0.056],[-5.024,-39.432],[-7.319,-40.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[255.318,256.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"mute Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[100,88.781,0],"e":[85,88.781,0],"to":[-2.5,0,0],"ti":[2.5,0,0]},{"t":10}],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.872,0.872,-11.778]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p872_0p333_0","0p833_0p872_0p333_0","0p833_-11p778_0p333_0"],"t":0,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.426,0.426,6.389]},"n":["0p667_1_0p167_0p426","0p667_1_0p167_0p426","0p667_1_0p167_6p389"],"t":10,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":15,"s":[115,115,100],"e":[100,100,100]},{"t":25}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.995,-0.904],[0,0],[0.746,0],[0,0],[0,-3.866],[0,0],[-3.866,0],[0,0],[-0.552,-0.503],[0,0],[-2.006,2.207],[0,1.343],[0,0],[2.982,0]],"o":[[0,0],[-0.552,0.502],[0,0],[-3.866,0],[0,0],[0,3.866],[0,0],[0.746,0],[0,0],[2.207,2.007],[0.903,-0.995],[0,0],[0,-2.982],[-1.343,0]],"v":[[16.967,-36.589],[-6.142,-15.581],[-8.16,-14.801],[-19,-14.801],[-26,-7.801],[-26,7.199],[-19,14.199],[-8.16,14.199],[-6.142,14.98],[16.967,35.987],[24.596,35.625],[26,31.992],[26,-32.594],[20.6,-37.994]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[256,256.994],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TelegramUI/Resources/Animations/anim_unpin.json b/TelegramUI/Resources/Animations/anim_unpin.json new file mode 100644 index 0000000000..3a0750f7a8 --- /dev/null +++ b/TelegramUI/Resources/Animations/anim_unpin.json @@ -0,0 +1 @@ +{"v":"5.1.2","fr":60,"ip":0,"op":3600,"w":228,"h":228,"nm":"unpinpinchat","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"un Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[118,84.062,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.872,0.872,-11.778]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p872_0p333_0","0p833_0p872_0p333_0","0p833_-11p778_0p333_0"],"t":0,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.426,0.426,6.389]},"n":["0p667_1_0p167_0p426","0p667_1_0p167_0p426","0p667_1_0p167_6p389"],"t":10,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":15,"s":[115,115,100],"e":[100,100,100]},{"t":24}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":5,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-34,-34],[-33.992,-34]],"c":false}],"e":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-34,-34],[34,34]],"c":false}]},{"t":15}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"ix":5},"lc":2,"lj":1,"ml":10,"nm":"Stroke 2","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"st","c":{"a":0,"k":[0.097999999102,0.57599995931,0.980000035903,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":15,"ix":5},"lc":2,"lj":1,"ml":10,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[256,256],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"pin Outlines","sr":1,"ks":{"o":{"a":0,"k":99,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[113.656,86.516,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.859,0.859,-13.056]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p859_0p333_0","0p833_0p859_0p333_0","0p833_-13p056_0p333_0"],"t":0,"s":[0,0,100],"e":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.341,0.341,5.111]},"n":["0p667_1_0p167_0p341","0p667_1_0p167_0p341","0p667_1_0p167_5p111"],"t":11,"s":[100,100,100],"e":[115,115,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":15,"s":[115,115,100],"e":[100,100,100]},{"t":24}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.682,-2.385],[0,0],[7.227,-5.009],[0.494,-0.402],[0.078,-0.079],[-1.265,-1.266],[0,0],[-0.087,-0.07],[-1.129,1.388],[-0.211,0.297],[2.361,8.281],[0,0],[3.76,3.76],[0,0],[2.035,0]],"o":[[0,0],[-8.176,-2.331],[-0.37,0.258],[-0.086,0.07],[-1.265,1.265],[0,0],[0.079,0.078],[1.388,1.129],[0.312,-0.384],[5.172,-7.273],[0,0],[4.348,-3.067],[0,0],[-1.701,-1.701],[-2.465,0]],"v":[[10.943,-36.491],[-1.24,-19.219],[-25.643,-15.202],[-26.94,-14.213],[-27.187,-13.99],[-27.187,-9.408],[8.801,26.579],[9.049,26.802],[13.607,26.332],[14.391,25.311],[18.607,0.628],[35.879,-11.556],[36.955,-23.925],[23.313,-37.567],[17.514,-40.1]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-40.714,40.1],[-7.985,15.793],[-16.406,7.372]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[256.714,257.1],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TelegramUI/Resources/Animations/anim_unread.json b/TelegramUI/Resources/Animations/anim_unread.json new file mode 100644 index 0000000000..b648c6da3f --- /dev/null +++ b/TelegramUI/Resources/Animations/anim_unread.json @@ -0,0 +1 @@ +{"v":"4.5.6","fr":60,"ip":0,"op":30,"w":228,"h":228,"ddd":0,"assets":[],"layers":[{"ddd":0,"ind":0,"ty":4,"nm":"Oval","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[144,60,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,0.667]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p667_1_0p167_0p167","0p667_1_0p167_0p167","0p667_0p667_0p167_0p167"],"t":10,"s":[0,0,100],"e":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,0.667]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_0p667_0p333_0p333"],"t":19,"s":[110,110,100],"e":[100,100,100]},{"t":24}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[24,24]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[0.13,0.58,0.98,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":5.333},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval","np":3,"mn":"ADBE Vector Group"}],"ip":0,"op":30,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":1,"ty":4,"nm":"Combined Shape","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[114,89.499,0]},"a":{"a":0,"k":[40,38.499,0]},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,0.667]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p667_1_0p167_0p167","0p667_1_0p167_0p167","0p667_0p667_0p167_0p167"],"t":0,"s":[0,0,100],"e":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,0.667]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_0p667_0p333_0p333"],"t":15,"s":[110,110,100],"e":[100,100,100]},{"t":20}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.39,0],[0,19.29],[22.09,0],[0,-19.28],[-9.1,-6.4],[2.59,-3.82],[-1.62,-0.65],[-4.27,2.3],[-1.31,-0.29]],"o":[[22.09,0],[0,-19.28],[-22.09,0],[0,11],[1.17,0.82],[-2.6,3.82],[1,0.4],[6.1,-3.28],[3.14,0.69]],"v":[[40,69.85],[80,34.92],[40,0],[0,34.92],[14.45,61.34],[14.1,70.53],[9.89,76.75],[21.07,75.05],[30.18,68.79]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"mn":"ADBE Vector Group"}],"ip":0,"op":30,"st":0,"bm":0,"sr":1}]} \ No newline at end of file diff --git a/TelegramUI/SettingsController.swift b/TelegramUI/SettingsController.swift index 0bae4bc1aa..382ee388b6 100644 --- a/TelegramUI/SettingsController.swift +++ b/TelegramUI/SettingsController.swift @@ -284,7 +284,7 @@ private enum SettingsEntry: ItemListNodeEntry { arguments.openRecentCalls() }) case let .stickers(theme, image, text, value): - return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: value, sectionId: ItemListSectionId(self.section), style: .blocks, action: { + return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: value, labelStyle: .badge, sectionId: ItemListSectionId(self.section), style: .blocks, action: { arguments.pushController(installedStickerPacksController(account: arguments.account, mode: .general)) }) case let .notificationsAndSounds(theme, image, text): diff --git a/TelegramUI/StickerPackPreviewControllerNode.swift b/TelegramUI/StickerPackPreviewControllerNode.swift index a30113e4da..62b29035db 100644 --- a/TelegramUI/StickerPackPreviewControllerNode.swift +++ b/TelegramUI/StickerPackPreviewControllerNode.swift @@ -40,6 +40,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol private var stickerPack: LoadedStickerPack? private var stickerPackUpdated = false + private var stickerPackInitiallyInstalled : Bool? private var didSetItems = false @@ -425,16 +426,27 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol } @objc func installActionButtonPressed() { + let dismissOnAction: Bool + if let initiallyInstalled = self.stickerPackInitiallyInstalled, initiallyInstalled { + dismissOnAction = false + } else { + dismissOnAction = true + } if let stickerPack = self.stickerPack { switch stickerPack { case let .result(info, items, installed): if installed { let _ = removeStickerPackInteractively(postbox: self.account.postbox, id: info.id, option: .delete).start() - self.cancelButtonPressed() + updateStickerPack(.result(info: info, items: items, installed: false)) } else { let _ = addStickerPackInteractively(postbox: self.account.postbox, info: info, items: items).start() + if !dismissOnAction { + updateStickerPack(.result(info: info, items: items, installed: true)) + } + } + if dismissOnAction { self.cancelButtonPressed() - } + } default: break } @@ -487,6 +499,9 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol self.installActionSeparatorNode.alpha = 0.0 self.installActionButtonNode.setTitle("", with: Font.medium(20.0), with: self.presentationData.theme.actionSheet.standardActionTextColor, for: .normal) case let .result(info, _, installed): + if self.stickerPackInitiallyInstalled == nil { + self.stickerPackInitiallyInstalled = installed + } self.installActionSeparatorNode.alpha = 1.0 if installed { let text: String diff --git a/TelegramUI/StorageUsageController.swift b/TelegramUI/StorageUsageController.swift index ccd0549802..ea5b0d5c7d 100644 --- a/TelegramUI/StorageUsageController.swift +++ b/TelegramUI/StorageUsageController.swift @@ -30,7 +30,7 @@ private enum StorageUsageEntry: ItemListNodeEntry { case collecting(PresentationTheme, String) - case clearAll(PresentationTheme, String, String) + case clearAll(PresentationTheme, String, String, Bool) case peersHeader(PresentationTheme, String) case peer(Int32, PresentationTheme, PresentationStrings, Peer, String) @@ -83,8 +83,8 @@ private enum StorageUsageEntry: ItemListNodeEntry { } else { return false } - case let .clearAll(lhsTheme, lhsText, lhsValue): - if case let .clearAll(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { + case let .clearAll(lhsTheme, lhsText, lhsValue, lhsEnabled): + if case let .clearAll(rhsTheme, rhsText, rhsValue, rhsEnabled) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsEnabled == rhsEnabled { return true } else { return false @@ -135,8 +135,8 @@ private enum StorageUsageEntry: ItemListNodeEntry { return CalculatingCacheSizeItem(theme: theme, title: text, sectionId: self.section, style: .blocks) case let .peersHeader(theme, text): return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) - case let .clearAll(theme, text, value): - return ItemListDisclosureItem(theme: theme, icon: nil, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + case let .clearAll(theme, text, value, enabled): + return ItemListDisclosureItem(theme: theme, icon: nil, title: text, kind: enabled ? .generic : .disabled, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { arguments.openClearAll() }) case let .peer(_, theme, strings, peer, value): @@ -181,7 +181,9 @@ private func storageUsageControllerEntries(presentationData: PresentationData, c peerSizes += combinedSize } - entries.append(.clearAll(presentationData.theme, presentationData.strings.Cache_ClearCache, dataSizeString(Int(peerSizes + stats.otherSize + stats.cacheSize + stats.tempSize)))) + let totalSize = Int(peerSizes + stats.otherSize + stats.cacheSize + stats.tempSize) + + entries.append(.clearAll(presentationData.theme, presentationData.strings.Cache_ClearCache, totalSize > 0 ? dataSizeString(totalSize) : presentationData.strings.Cache_ClearEmpty, totalSize > 0)) var index: Int32 = 0 for (peerId, size) in statsByPeerId.sorted(by: { $0.1 > $1.1 }) { diff --git a/TelegramUI/TGChannelIntroController.h b/TelegramUI/TGChannelIntroController.h index f93aee2615..3eb7a0f481 100644 --- a/TelegramUI/TGChannelIntroController.h +++ b/TelegramUI/TGChannelIntroController.h @@ -15,6 +15,6 @@ @interface TGChannelIntroController : TGViewController -- (instancetype)initWithContext:(id)context getLocalizedString:(NSString *(^)(NSString *))getLocalizedString theme:(TGChannelIntroControllerTheme *)theme completion:(void (^)(void))completion; +- (instancetype)initWithContext:(id)context getLocalizedString:(NSString *(^)(NSString *))getLocalizedString theme:(TGChannelIntroControllerTheme *)theme dismiss:(void (^)(void))dismiss completion:(void (^)(void))completion; @end diff --git a/TelegramUI/TGChannelIntroController.m b/TelegramUI/TGChannelIntroController.m index eb9c049c5d..b63d886fa3 100644 --- a/TelegramUI/TGChannelIntroController.m +++ b/TelegramUI/TGChannelIntroController.m @@ -29,17 +29,19 @@ TGModernButton *_createButton; TGChannelIntroControllerTheme *_theme; NSString *(^_getLocalizedString)(NSString *); + void (^_dismiss)(void); void (^_completion)(void); } @end @implementation TGChannelIntroController -- (instancetype)initWithContext:(id)context getLocalizedString:(NSString *(^)(NSString *))getLocalizedString theme:(TGChannelIntroControllerTheme *)theme completion:(void (^)(void))completion { +- (instancetype)initWithContext:(id)context getLocalizedString:(NSString *(^)(NSString *))getLocalizedString theme:(TGChannelIntroControllerTheme *)theme dismiss:(void (^)(void))dismiss completion:(void (^)(void))completion { self = [super initWithContext:context]; if (self != nil) { _getLocalizedString = [getLocalizedString copy]; _theme = theme; + _dismiss = [dismiss copy]; _completion = [completion copy]; } return self; @@ -119,7 +121,10 @@ - (void)backButtonPressed { - [self.navigationController popViewControllerAnimated:true]; + if (_dismiss != nil) + _dismiss(); + else + [self.navigationController popViewControllerAnimated:true]; } - (void)buttonPressed diff --git a/TelegramUI/TelegramAccountAuxiliaryMethods.swift b/TelegramUI/TelegramAccountAuxiliaryMethods.swift index 881b9a73bb..715c53be4c 100644 --- a/TelegramUI/TelegramAccountAuxiliaryMethods.swift +++ b/TelegramUI/TelegramAccountAuxiliaryMethods.swift @@ -26,7 +26,7 @@ public let telegramAccountAuxiliaryMethods = AccountAuxiliaryMethods(updatePeerC } else if let resource = resource as? SecureIdLocalImageResource { return fetchSecureIdLocalImageResource(postbox: account.postbox, resource: resource) } else if let resource = resource as? OpenInAppIconResource { - return fetchOpenInAppIconResource(account: account, resource: resource) + return fetchOpenInAppIconResource(resource: resource) } return nil }, fetchResourceMediaReferenceHash: { resource in diff --git a/TelegramUI/TelegramController.swift b/TelegramUI/TelegramController.swift index 5485921f14..eb6b8bac8a 100644 --- a/TelegramUI/TelegramController.swift +++ b/TelegramUI/TelegramController.swift @@ -244,8 +244,10 @@ public class TelegramController: ViewController { } items.append(ActionSheetButtonItem(title: presentationData.strings.LiveLocation_MenuStopAll, color: .destructive, action: { dismissAction() - for peer in locationBroadcastPeers { - self?.account.telegramApplicationContext.liveLocationManager?.cancelLiveLocation(peerId: peer.id) + if let locationBroadcastPeers = strongSelf.locationBroadcastPeers { + for peer in locationBroadcastPeers { + self?.account.telegramApplicationContext.liveLocationManager?.cancelLiveLocation(peerId: peer.id) + } } })) } diff --git a/TelegramUI/TelegramRootController.swift b/TelegramUI/TelegramRootController.swift index 6fcfb7b4c2..a46352909f 100644 --- a/TelegramUI/TelegramRootController.swift +++ b/TelegramUI/TelegramRootController.swift @@ -110,6 +110,6 @@ public final class TelegramRootController: NavigationController { guard let controller = self.viewControllers.last as? ViewController else { return } - presentedLegacyShortcutCamera(account: self.account, saveCapturedMedia: false, saveEditedPhotos: false, parentController: controller) + presentedLegacyShortcutCamera(account: self.account, saveCapturedMedia: false, saveEditedPhotos: false, mediaGrouping: true, parentController: controller) } } diff --git a/TelegramUI/ThemeGalleryController.swift b/TelegramUI/ThemeGalleryController.swift index 5084a8ae1b..f12fbbfc85 100644 --- a/TelegramUI/ThemeGalleryController.swift +++ b/TelegramUI/ThemeGalleryController.swift @@ -231,7 +231,8 @@ class ThemeGalleryController: ViewController { self.galleryNode.backgroundNode.isOpaque = false self.galleryNode.isBackgroundExtendedOverNavigationBar = true - let toolbarNode = ThemeGalleryToolbarNode() + let presentationData = self.account.telegramApplicationContext.currentPresentationData.with { $0 } + let toolbarNode = ThemeGalleryToolbarNode(strings: presentationData.strings) self.toolbarNode = toolbarNode self.galleryNode.addSubnode(toolbarNode) self.galleryNode.toolbarNode = toolbarNode @@ -295,8 +296,8 @@ class ThemeGalleryController: ViewController { self.galleryNode.frame = CGRect(origin: CGPoint(), size: layout.size) self.galleryNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationHeight, transition: transition) - transition.updateFrame(node: self.toolbarNode!, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - 49.0), size: CGSize(width: layout.size.width, height: 49.0))) - self.toolbarNode!.updateLayout(size: CGSize(width: layout.size.width, height: 49.0), transition: transition) + transition.updateFrame(node: self.toolbarNode!, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - 49.0 - layout.intrinsicInsets.bottom), size: CGSize(width: layout.size.width, height: 49.0 + layout.intrinsicInsets.bottom))) + self.toolbarNode!.updateLayout(size: CGSize(width: layout.size.width, height: 49.0), layout: layout, transition: transition) let replace = self.validLayout == nil self.validLayout = (layout, 0.0) diff --git a/TelegramUI/ThemeGalleryToolbarNode.swift b/TelegramUI/ThemeGalleryToolbarNode.swift index b7d7dcf589..62bd1c48ac 100644 --- a/TelegramUI/ThemeGalleryToolbarNode.swift +++ b/TelegramUI/ThemeGalleryToolbarNode.swift @@ -11,7 +11,7 @@ final class ThemeGalleryToolbarNode: ASDisplayNode { var cancel: (() -> Void)? var done: (() -> Void)? - override init() { + init(strings: PresentationStrings) { super.init() self.addSubnode(self.cancelButton) @@ -23,8 +23,8 @@ final class ThemeGalleryToolbarNode: ASDisplayNode { self.separatorNode.backgroundColor = .black self.topSeparatorNode.backgroundColor = .black - self.cancelButton.setTitle("Cancel", with: Font.regular(17.0), with: .black, for: []) - self.doneButton.setTitle("Set", with: Font.regular(17.0), with: .black, for: []) + self.cancelButton.setTitle(strings.Common_Cancel, with: Font.regular(17.0), with: .black, for: []) + self.doneButton.setTitle(strings.Wallpaper_Set, with: Font.regular(17.0), with: .black, for: []) self.cancelButton.highligthedChanged = { [weak self] highlighted in if let strongSelf = self { @@ -54,10 +54,10 @@ final class ThemeGalleryToolbarNode: ASDisplayNode { self.doneButton.addTarget(self, action: #selector(self.donePressed), forControlEvents: .touchUpInside) } - func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) { + func updateLayout(size: CGSize, layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { self.cancelButton.frame = CGRect(origin: CGPoint(), size: CGSize(width: floor(size.width / 2.0), height: size.height)) self.doneButton.frame = CGRect(origin: CGPoint(x: floor(size.width / 2.0), y: 0.0), size: CGSize(width: size.width - floor(size.width / 2.0), height: size.height)) - self.separatorNode.frame = CGRect(origin: CGPoint(x: floor(size.width / 2.0), y: 0.0), size: CGSize(width: UIScreenPixel, height: size.height)) + self.separatorNode.frame = CGRect(origin: CGPoint(x: floor(size.width / 2.0), y: 0.0), size: CGSize(width: UIScreenPixel, height: size.height + layout.intrinsicInsets.bottom)) self.topSeparatorNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: UIScreenPixel)) } diff --git a/TelegramUI/UserInfoController.swift b/TelegramUI/UserInfoController.swift index 80bec046f1..493be9fa36 100644 --- a/TelegramUI/UserInfoController.swift +++ b/TelegramUI/UserInfoController.swift @@ -28,9 +28,10 @@ private final class UserInfoControllerArguments { let addBotToGroup: () -> Void let botSettings: () -> Void let botHelp: () -> Void + let botPrivacy: () -> Void let report: () -> Void - init(account: Account, avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, tapAvatarAction: @escaping () -> Void, openChat: @escaping () -> Void, addContact: @escaping () -> Void, shareContact: @escaping () -> Void, startSecretChat: @escaping () -> Void, changeNotificationMuteSettings: @escaping () -> Void, changeNotificationSoundSettings: @escaping () -> Void, openSharedMedia: @escaping () -> Void, openGroupsInCommon: @escaping () -> Void, updatePeerBlocked: @escaping (Bool) -> Void, deleteContact: @escaping () -> Void, displayUsernameContextMenu: @escaping (String) -> Void, displayCopyContextMenu: @escaping (UserInfoEntryTag, String) -> Void, call: @escaping () -> Void, openCallMenu: @escaping (String) -> Void, displayAboutContextMenu: @escaping (String) -> Void, openEncryptionKey: @escaping (SecretChatKeyFingerprint) -> Void, addBotToGroup: @escaping () -> Void, botSettings: @escaping () -> Void, botHelp: @escaping () -> Void, report: @escaping () -> Void) { + init(account: Account, avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, tapAvatarAction: @escaping () -> Void, openChat: @escaping () -> Void, addContact: @escaping () -> Void, shareContact: @escaping () -> Void, startSecretChat: @escaping () -> Void, changeNotificationMuteSettings: @escaping () -> Void, changeNotificationSoundSettings: @escaping () -> Void, openSharedMedia: @escaping () -> Void, openGroupsInCommon: @escaping () -> Void, updatePeerBlocked: @escaping (Bool) -> Void, deleteContact: @escaping () -> Void, displayUsernameContextMenu: @escaping (String) -> Void, displayCopyContextMenu: @escaping (UserInfoEntryTag, String) -> Void, call: @escaping () -> Void, openCallMenu: @escaping (String) -> Void, displayAboutContextMenu: @escaping (String) -> Void, openEncryptionKey: @escaping (SecretChatKeyFingerprint) -> Void, addBotToGroup: @escaping () -> Void, botSettings: @escaping () -> Void, botHelp: @escaping () -> Void, botPrivacy: @escaping () -> Void, report: @escaping () -> Void) { self.account = account self.avatarAndNameInfoContext = avatarAndNameInfoContext self.updateEditingName = updateEditingName @@ -54,6 +55,7 @@ private final class UserInfoControllerArguments { self.addBotToGroup = addBotToGroup self.botSettings = botSettings self.botHelp = botHelp + self.botPrivacy = botPrivacy self.report = report } } @@ -89,6 +91,7 @@ private enum UserInfoEntry: ItemListNodeEntry { case botAddToGroup(PresentationTheme, String) case botSettings(PresentationTheme, String) case botHelp(PresentationTheme, String) + case botPrivacy(PresentationTheme, String) case botReport(PresentationTheme, String) case block(PresentationTheme, String, DestructiveUserInfoAction) @@ -100,7 +103,7 @@ private enum UserInfoEntry: ItemListNodeEntry { return UserInfoSection.actions.rawValue case .sharedMedia, .notifications, .notificationSound, .secretEncryptionKey, .groupsInCommon: return UserInfoSection.sharedMediaAndNotifications.rawValue - case .botAddToGroup, .botSettings, .botHelp, .botReport: + case .botAddToGroup, .botSettings, .botHelp, .botPrivacy, .botReport: return UserInfoSection.bot.rawValue case .block: return UserInfoSection.block.rawValue @@ -243,6 +246,12 @@ private enum UserInfoEntry: ItemListNodeEntry { } else { return false } + case let .botPrivacy(lhsTheme, lhsText): + if case let .botPrivacy(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } case let .botReport(lhsTheme, lhsText): if case let .botReport(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { return true @@ -292,10 +301,12 @@ private enum UserInfoEntry: ItemListNodeEntry { return 1011 case .botHelp: return 1012 - case .botReport: + case .botPrivacy: return 1013 - case .block: + case .botReport: return 1014 + case .block: + return 1015 } } @@ -318,7 +329,7 @@ private enum UserInfoEntry: ItemListNodeEntry { arguments.displayAboutContextMenu(value) }, tag: UserInfoEntryTag.about) case let .phoneNumber(theme, _, label, value, isMain): - return ItemListTextWithLabelItem(theme: theme, label: label, text: value, textColor: .accent, enabledEntitiyTypes: [], multiline: false, sectionId: self.section, action: { + return ItemListTextWithLabelItem(theme: theme, label: label, text: value, textColor: isMain ? .highlighted : .accent, enabledEntitiyTypes: [], multiline: false, sectionId: self.section, action: { arguments.openCallMenu(value) }, longTapAction: { arguments.displayCopyContextMenu(.phoneNumber, value) @@ -377,6 +388,10 @@ private enum UserInfoEntry: ItemListNodeEntry { return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: { arguments.botHelp() }) + case let .botPrivacy(theme, text): + return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: { + arguments.botPrivacy() + }) case let .botReport(theme, text): return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: { arguments.report() @@ -516,7 +531,7 @@ private func userInfoEntries(account: Account, presentationData: PresentationDat index += 1 } else { for (number, isMain) in phoneNumbers { - entries.append(UserInfoEntry.phoneNumber(presentationData.theme, index, localizedPhoneNumberLabel(label: number.label, strings: presentationData.strings), number.number.normalized.rawValue, isMain && phoneNumbers.count != 1)) + entries.append(UserInfoEntry.phoneNumber(presentationData.theme, index, localizedPhoneNumberLabel(label: number.label, strings: presentationData.strings), number.number.normalized.rawValue, isMain && phoneNumbers.count != 1)) index += 1 } } @@ -540,7 +555,10 @@ private func userInfoEntries(account: Account, presentationData: PresentationDat } else if let phone = user.phone, !phone.isEmpty { entries.append(UserInfoEntry.addContact(presentationData.theme, presentationData.strings.UserInfo_AddContact)) } - entries.append(UserInfoEntry.startSecretChat(presentationData.theme, presentationData.strings.UserInfo_StartSecretChat)) + + if let peer = peer as? TelegramUser, peer.botInfo == nil { + entries.append(UserInfoEntry.startSecretChat(presentationData.theme, presentationData.strings.UserInfo_StartSecretChat)) + } } entries.append(UserInfoEntry.sharedMedia(presentationData.theme, presentationData.strings.GroupInfo_SharedMedia)) } @@ -575,8 +593,19 @@ private func userInfoEntries(account: Account, presentationData: PresentationDat if botInfo.flags.contains(.worksWithGroups) { entries.append(UserInfoEntry.botAddToGroup(presentationData.theme, presentationData.strings.UserInfo_InviteBotToGroup)) } - entries.append(UserInfoEntry.botSettings(presentationData.theme, presentationData.strings.UserInfo_BotSettings)) - entries.append(UserInfoEntry.botHelp(presentationData.theme, presentationData.strings.UserInfo_BotHelp)) + + if let cachedUserData = view.cachedData as? CachedUserData, let botInfo = cachedUserData.botInfo { + for command in botInfo.commands { + if command.text == "settings" { + entries.append(UserInfoEntry.botSettings(presentationData.theme, presentationData.strings.UserInfo_BotSettings)) + } else if command.text == "help" { + entries.append(UserInfoEntry.botHelp(presentationData.theme, presentationData.strings.UserInfo_BotHelp)) + } else if command.text == "privacy" { + entries.append(UserInfoEntry.botPrivacy(presentationData.theme, presentationData.strings.UserInfo_BotPrivacy)) + } + } + } + entries.append(UserInfoEntry.botReport(presentationData.theme, presentationData.strings.ReportPeer_Report)) } @@ -888,6 +917,12 @@ public func userInfoController(account: Account, peerId: PeerId) -> ViewControll let _ = enqueueMessages(account: account, peerId: peer.id, messages: [.message(text: "/help", attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil)]).start() openChatImpl?() }) + }, botPrivacy: { + let _ = (account.postbox.loadedPeerWithId(peerId) + |> deliverOnMainQueue).start(next: { peer in + let _ = enqueueMessages(account: account, peerId: peer.id, messages: [.message(text: "/privacy", attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil)]).start() + openChatImpl?() + }) }, report: { presentControllerImpl?(peerReportOptionsController(account: account, subject: .peer(peerId), present: { c, a in presentControllerImpl?(c, a) @@ -1152,7 +1187,7 @@ public func userInfoController(account: Account, peerId: PeerId) -> ViewControll let _ = strongController.frameForItemNode({ itemNode in if let itemNode = itemNode as? ItemListTextWithLabelItemNode { if let itemTag = itemNode.tag as? UserInfoEntryTag { - if itemTag == tag { + if itemTag == tag && itemNode.item?.text == value { resultItemNode = itemNode return true } @@ -1222,5 +1257,7 @@ public func userInfoController(account: Account, peerId: PeerId) -> ViewControll } } + controller.navigationItem.backBarButtonItem = UIBarButtonItem(title: account.telegramApplicationContext.currentPresentationData.with{ $0 }.strings.Common_Back, style: .plain, target: nil, action: nil) + return controller } diff --git a/TelegramUI/VimeoEmbedImplementation.swift b/TelegramUI/VimeoEmbedImplementation.swift index 54ed30cad8..e2434a41b5 100644 --- a/TelegramUI/VimeoEmbedImplementation.swift +++ b/TelegramUI/VimeoEmbedImplementation.swift @@ -72,7 +72,7 @@ final class VimeoEmbedImplementation: WebEmbedImplementation { init(videoId: String, timestamp: Int = 0) { self.videoId = videoId self.timestamp = timestamp - self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true)) + self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true)) } func setup(_ webView: WKWebView, userContentController: WKUserContentController, evaluateJavaScript: @escaping (String) -> Void, updateStatus: @escaping (MediaPlayerStatus) -> Void, onPlaybackStarted: @escaping () -> Void) { @@ -135,7 +135,7 @@ final class VimeoEmbedImplementation: WebEmbedImplementation { eval("seek(\(timestamp));") } - self.status = MediaPlayerStatus(generationTimestamp: self.status.generationTimestamp, duration: self.status.duration, dimensions: self.status.dimensions, timestamp: timestamp, seekId: self.status.seekId + 1, status: self.status.status) + self.status = MediaPlayerStatus(generationTimestamp: self.status.generationTimestamp, duration: self.status.duration, dimensions: self.status.dimensions, timestamp: timestamp, baseRate: 1.0, seekId: self.status.seekId + 1, status: self.status.status) if let updateStatus = self.updateStatus { updateStatus(self.status) } @@ -199,7 +199,7 @@ final class VimeoEmbedImplementation: WebEmbedImplementation { playbackStatus = .buffering(initial: true, whilePlaying: false) } - self.status = MediaPlayerStatus(generationTimestamp: self.status.generationTimestamp, duration: Double(duration), dimensions: self.status.dimensions, timestamp: newTimestamp, seekId: self.status.seekId, status: playbackStatus) + self.status = MediaPlayerStatus(generationTimestamp: self.status.generationTimestamp, duration: Double(duration), dimensions: self.status.dimensions, timestamp: newTimestamp, baseRate: 1.0, seekId: self.status.seekId, status: playbackStatus) updateStatus(self.status) } } diff --git a/TelegramUI/WebEmbedPlayerNode.swift b/TelegramUI/WebEmbedPlayerNode.swift index d8812af13c..b83fc20ebb 100644 --- a/TelegramUI/WebEmbedPlayerNode.swift +++ b/TelegramUI/WebEmbedPlayerNode.swift @@ -26,7 +26,7 @@ func webEmbedImplementation(embedUrl: String, url: String) -> WebEmbedImplementa } final class WebEmbedPlayerNode: ASDisplayNode, WKNavigationDelegate { - private let statusValue = ValuePromise(MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, seekId: 0, status: .paused), ignoreRepeated: true) + private let statusValue = ValuePromise(MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .paused), ignoreRepeated: true) var status: Signal { return self.statusValue.get() diff --git a/TelegramUI/YoutubeEmbedImplementation.swift b/TelegramUI/YoutubeEmbedImplementation.swift index 8926d650d9..24ef384627 100644 --- a/TelegramUI/YoutubeEmbedImplementation.swift +++ b/TelegramUI/YoutubeEmbedImplementation.swift @@ -103,7 +103,7 @@ final class YoutubeEmbedImplementation: WebEmbedImplementation { init(videoId: String, timestamp: Int = 0) { self.videoId = videoId self.timestamp = timestamp - self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: Double(timestamp), seekId: 0, status: .buffering(initial: true, whilePlaying: true)) + self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: Double(timestamp), baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true)) } func setup(_ webView: WKWebView, userContentController: WKUserContentController, evaluateJavaScript: @escaping (String) -> Void, updateStatus: @escaping (MediaPlayerStatus) -> Void, onPlaybackStarted: @escaping () -> Void) { @@ -190,7 +190,7 @@ final class YoutubeEmbedImplementation: WebEmbedImplementation { eval("seek(\(timestamp));") } - self.status = MediaPlayerStatus(generationTimestamp: self.status.generationTimestamp, duration: self.status.duration, dimensions: self.status.dimensions, timestamp: timestamp, seekId: self.status.seekId + 1, status: self.status.status) + self.status = MediaPlayerStatus(generationTimestamp: self.status.generationTimestamp, duration: self.status.duration, dimensions: self.status.dimensions, timestamp: timestamp, baseRate: 1.0, seekId: self.status.seekId + 1, status: self.status.status) if let updateStatus = self.updateStatus { updateStatus(self.status) } @@ -257,7 +257,7 @@ final class YoutubeEmbedImplementation: WebEmbedImplementation { playbackStatus = .buffering(initial: true, whilePlaying: false) } - self.status = MediaPlayerStatus(generationTimestamp: self.status.generationTimestamp, duration: Double(duration), dimensions: self.status.dimensions, timestamp: newTimestamp, seekId: 0, status: playbackStatus) + self.status = MediaPlayerStatus(generationTimestamp: self.status.generationTimestamp, duration: Double(duration), dimensions: self.status.dimensions, timestamp: newTimestamp, baseRate: 1.0, seekId: 0, status: playbackStatus) updateStatus(self.status) } } diff --git a/third-party/RMIntro/core/animations.c b/third-party/RMIntro/core/animations.c index 6755a80488..0f17afdb59 100644 --- a/third-party/RMIntro/core/animations.c +++ b/third-party/RMIntro/core/animations.c @@ -1889,8 +1889,6 @@ void on_draw_frame() { draw_textured_shape(&fast_arrow, main_matrix, NORMAL_ONE); } } - - else if (current_page == 1) { glEnable(GL_BLEND); @@ -1953,10 +1951,7 @@ void on_draw_frame() { draw_ic(0); } } - - else if (current_page == 2) { - glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); @@ -2001,11 +1996,8 @@ void on_draw_frame() { ribbon3.params.rotation = 180; ribbon4.params.rotation = 270; } - - else if (current_page == 3) { if (direct == 1) { - glDisable(GL_BLEND); free_bg.params.alpha = 1; draw_shape(&free_bg, main_matrix); @@ -2018,7 +2010,6 @@ void on_draw_frame() { draw_stars(); } else { - glDisable(GL_BLEND); private_bg.params.alpha = 1; draw_shape(&private_bg, main_matrix); @@ -2034,12 +2025,9 @@ void on_draw_frame() { draw_stars(); } } - - else if (current_page == 4) { if (direct == 1) { - glDisable(GL_BLEND); powerful_bg.params.alpha = 1; draw_shape(&powerful_bg, main_matrix); @@ -2066,8 +2054,6 @@ void on_draw_frame() { draw_shape(&private_bg, main_matrix); } } - - else if (current_page == 5) { glDisable(GL_BLEND); @@ -2104,7 +2090,7 @@ void on_draw_frame() { telegram_sphere.params.alpha = t(0, 1, 0, duration_const*.8, Linear); - scale = 1; + scale = 1.01; telegram_sphere.params.scale = xyzMake(scale, scale, 1); draw_textured_shape(&telegram_sphere, main_matrix, NORMAL); @@ -2126,11 +2112,8 @@ void on_draw_frame() { } } } - - else if (current_page==1) { - rglNormalDraw(); if (direct == 1) { @@ -2155,8 +2138,6 @@ void on_draw_frame() { } } } - - else if (current_page == 2) { rglNormalDrawThroughMask(); @@ -2227,7 +2208,6 @@ void on_draw_frame() { } else { - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); float scale = t(1, 2, 0, duration_const, EaseIn); @@ -2334,7 +2314,6 @@ void on_draw_frame() { else if (current_page == 3) { - if (direct == 1) { // reset ribbons positions diff --git a/third-party/RMIntro/platform/ios/RMIntroViewController.h b/third-party/RMIntro/platform/ios/RMIntroViewController.h index 845b715da7..35995654ae 100644 --- a/third-party/RMIntro/platform/ios/RMIntroViewController.h +++ b/third-party/RMIntro/platform/ios/RMIntroViewController.h @@ -8,16 +8,6 @@ #import #import -//#import "RMRootViewController.h" - -typedef enum { - Inch35 = 0, - Inch4 = 1, - Inch47 = 2, - Inch55 = 3, - iPad = 4, - iPadPro = 5 -} DeviceScreen; @class SSignal; @@ -64,7 +54,7 @@ typedef enum { BOOL _isOpenGLLoaded; } -- (instancetype)initWithBackroundColor:(UIColor *)backgroundColor primaryColor:(UIColor *)primaryColor accentColor:(UIColor *)accentColor regularDotColor:(UIColor *)regularDotColor highlightedDotColor:(UIColor *)highlightedDotColor suggestedLocalizationSignal:(SSignal *)suggestedLocalizationSignal; +- (instancetype)initWithBackroundColor:(UIColor *)backgroundColor primaryColor:(UIColor *)primaryColor buttonColor:(UIColor *)buttonColor accentColor:(UIColor *)accentColor regularDotColor:(UIColor *)regularDotColor highlightedDotColor:(UIColor *)highlightedDotColor suggestedLocalizationSignal:(SSignal *)suggestedLocalizationSignal; @property (nonatomic, copy) void (^startMessaging)(void); @property (nonatomic, copy) void (^startMessagingInAlternativeLanguage)(NSString *); diff --git a/third-party/RMIntro/platform/ios/RMIntroViewController.m b/third-party/RMIntro/platform/ios/RMIntroViewController.m index fbe8997ba4..71746485d5 100644 --- a/third-party/RMIntro/platform/ios/RMIntroViewController.m +++ b/third-party/RMIntro/platform/ios/RMIntroViewController.m @@ -23,6 +23,15 @@ #define TGLog NSLog #define TGLocalized(x) NSLocalizedString(x, @"") +typedef enum { + Inch35 = 0, + Inch4 = 1, + Inch47 = 2, + Inch55 = 3, + iPad = 4, + iPadPro = 5 +} DeviceScreen; + static void TGDispatchOnMainThread(dispatch_block_t block) { if ([NSThread isMainThread]) { block(); @@ -71,11 +80,9 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { id _didEnterBackgroundObserver; id _willEnterBackgroundObserver; - UIImageView *_stillLogoView; - bool _displayedStillLogo; - UIColor *_backgroundColor; UIColor *_primaryColor; + UIColor *_buttonColor; UIColor *_accentColor; UIColor *_regularDotColor; UIColor *_highlightedDotColor; @@ -93,7 +100,7 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { @implementation RMIntroViewController -- (instancetype)initWithBackroundColor:(UIColor *)backgroundColor primaryColor:(UIColor *)primaryColor accentColor:(UIColor *)accentColor regularDotColor:(UIColor *)regularDotColor highlightedDotColor:(UIColor *)highlightedDotColor suggestedLocalizationSignal:(SSignal *)suggestedLocalizationSignal +- (instancetype)initWithBackroundColor:(UIColor *)backgroundColor primaryColor:(UIColor *)primaryColor buttonColor:(UIColor *)buttonColor accentColor:(UIColor *)accentColor regularDotColor:(UIColor *)regularDotColor highlightedDotColor:(UIColor *)highlightedDotColor suggestedLocalizationSignal:(SSignal *)suggestedLocalizationSignal { self = [super init]; if (self != nil) @@ -102,6 +109,7 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { _backgroundColor = backgroundColor; _primaryColor = primaryColor; + _buttonColor = buttonColor; _accentColor = accentColor; _regularDotColor = regularDotColor; _highlightedDotColor = highlightedDotColor; @@ -139,7 +147,7 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { __strong RMIntroViewController *strongSelf = weakSelf; if (strongSelf != nil && next != nil) { if (strongSelf->_alternativeLocalizationInfo == nil) { - _alternativeLocalizationInfo = next; + strongSelf->_alternativeLocalizationInfo = next; [strongSelf->_alternativeLanguageButton setTitle:next.continueWithLanguageString forState:UIControlStateNormal]; strongSelf->_alternativeLanguageButton.hidden = false; @@ -201,7 +209,7 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { height += 138 / 2; _glkView = [[GLKView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width / 2 - size / 2, height, size, size) context:context]; - _glkView.backgroundColor = _backgroundColor; + //_glkView.backgroundColor = _backgroundColor; _glkView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; _glkView.drawableDepthFormat = GLKViewDrawableDepthFormat24; _glkView.drawableMultisample = GLKViewDrawableMultisample4X; @@ -217,10 +225,10 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { v1.backgroundColor = v2.backgroundColor = v3.backgroundColor = v4.backgroundColor = _backgroundColor; - [_glkView addSubview:v1]; - [_glkView addSubview:v2]; - [_glkView addSubview:v3]; - [_glkView addSubview:v4]; + //[_glkView addSubview:v1]; + //[_glkView addSubview:v2]; + //[_glkView addSubview:v3]; + //[_glkView addSubview:v4]; [self setupGL]; [self.view addSubview:_glkView]; @@ -255,8 +263,6 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { [self loadGL]; - bool isIpad = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad); - _pageScrollView = [[UIScrollView alloc]initWithFrame:self.view.bounds]; _pageScrollView.clipsToBounds = true; _pageScrollView.opaque = true; @@ -292,7 +298,7 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { { UIGraphicsBeginImageContextWithOptions(CGSizeMake(48.0, 48.0), false, 0.0f); CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, [_accentColor CGColor]); + CGContextSetFillColorWithColor(context, [_buttonColor CGColor]); CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 48.0f, 48.0f)); buttonBackgroundImage = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:24 topCapHeight:24]; UIGraphicsEndImageContext(); @@ -303,7 +309,7 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { CGFloat hue = 0.0f; CGFloat sat = 0.0f; CGFloat bri = 0.0f; - [_accentColor getHue:&hue saturation:&sat brightness:&bri alpha:nil]; + [_buttonColor getHue:&hue saturation:&sat brightness:&bri alpha:nil]; UIColor *color = [[UIColor alloc] initWithHue:hue saturation:sat brightness:bri * 0.7 alpha:1.0]; CGContextSetFillColorWithColor(context, [color CGColor]); CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 48.0f, 48.0f)); @@ -487,65 +493,6 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { [super viewWillAppear:animated]; [self loadGL]; - - if (_stillLogoView == nil && !_displayedStillLogo) - { - _displayedStillLogo = true; - - _stillLogoView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"telegram_logo_still.png"]]; - _stillLogoView.contentMode = UIViewContentModeCenter; - _stillLogoView.bounds = CGRectMake(0, 0, 200, 200); - - UIInterfaceOrientation isVertical = (self.view.bounds.size.height / self.view.bounds.size.width > 1.0f); - - CGFloat statusBarHeight = 0.0f; - - CGFloat glViewY = 0; - DeviceScreen deviceScreen = [self deviceScreen]; - switch (deviceScreen) - { - case iPad: - glViewY = isVertical ? 121 + 90 : 121; - break; - - case iPadPro: - glViewY = isVertical ? 221 + 110 : 221; - break; - - case Inch35: - glViewY = 62 - 20; - break; - - case Inch4: - glViewY = 62; - break; - - case Inch47: - glViewY = 62 + 25; - break; - - case Inch55: - glViewY = 62 + 45; - break; - - default: - break; - } - - _stillLogoView.frame = CGRectChangedOriginY(_glkView.frame, glViewY - statusBarHeight); - [self.view addSubview:_stillLogoView]; - } -} - -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - - if (_stillLogoView != nil) - { - [_stillLogoView removeFromSuperview]; - _stillLogoView = nil; - } } - (void)viewDidDisappear:(BOOL)animated @@ -553,10 +500,6 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { [super viewDidDisappear:animated]; [self freeGL]; - - [_stillLogoView removeFromSuperview]; - _stillLogoView = nil; - _displayedStillLogo = false; } - (void)startButtonPress @@ -569,15 +512,6 @@ static void TGDispatchOnMainThread(dispatch_block_t block) { - (void)updateAndRender { [_glkView display]; - - TGDispatchOnMainThread(^ - { - if (_stillLogoView != nil) - { - [_stillLogoView removeFromSuperview]; - _stillLogoView = nil; - } - }); } - (void)dealloc