Merge commit '9e7107ef4e1503e120f064994319bb8f07228116'

This commit is contained in:
Peter 2019-09-12 21:40:44 +04:00
commit 99c6240172
42 changed files with 3005 additions and 2784 deletions

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>5.12</string>
<string>5.11.1</string>
<key>CFBundleVersion</key>
<string>${BUILD_NUMBER}</string>
<key>NSExtension</key>

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>5.12</string>
<string>5.11.1</string>
<key>CFBundleVersion</key>
<string>${BUILD_NUMBER}</string>
<key>NSExtension</key>

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>5.12</string>
<string>5.11.1</string>
<key>CFBundleVersion</key>
<string>${BUILD_NUMBER}</string>
<key>NSExtension</key>

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>5.12</string>
<string>5.11.1</string>
<key>CFBundleVersion</key>
<string>${BUILD_NUMBER}</string>
<key>NSExtension</key>

View File

@ -185,7 +185,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>5.12</string>
<string>5.11.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>

View File

@ -4744,8 +4744,11 @@ Any member of this group will be able to see messages in the channel.";
"ContactList.Context.SendMessage" = "Send Message";
"ContactList.Context.StartSecretChat" = "Start Secret Chat";
"ContactList.Context.Call" = "Cal";
"ContactList.Context.Call" = "Call";
"Theme.Context.Apply" = "Apply";
"Settings.Context.Logout" = "Logout";
"Channel.EditAdmin.PermissionDeleteMessagesOfOthers" = "Delete Messages of Others";
"Channel.AdminLog.CanDeleteMessagesOfOthers" = "Delete Messages of Others";

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>5.12</string>
<string>5.11.1</string>
<key>CFBundleVersion</key>
<string>${BUILD_NUMBER}</string>
<key>UIDeviceFamily</key>

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>5.12</string>
<string>5.11.1</string>
<key>CFBundleVersion</key>
<string>${BUILD_NUMBER}</string>
<key>NSExtension</key>

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>5.12</string>
<string>5.11.1</string>
<key>CFBundleVersion</key>
<string>${BUILD_NUMBER}</string>
<key>NSExtension</key>

View File

@ -1019,7 +1019,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
}
@objc private func composePressed() {
(self.navigationController as? NavigationController)?.replaceAllButRootController(self.context.sharedContext.makeComposeController(context: self.context), animated: true)
let controller = self.context.sharedContext.makeComposeController(context: self.context)
self.present(controller, in: .window(.root))
//(self.navigationController as? NavigationController)?.replaceAllButRootController(self.context.sharedContext.makeComposeController(context: self.context), animated: true)
}
public func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {

View File

@ -255,7 +255,7 @@ open class NavigationController: UINavigationController, ContainableController,
private func layoutDataForConfiguration(_ layoutConfiguration: ControllerLayoutConfiguration, layout: ContainerViewLayout, index: Int) -> (CGRect, ContainerViewLayout) {
switch layoutConfiguration {
case .masterDetail:
let masterWidth: CGFloat = max(320.0, floor(layout.size.width / 3.0))
let masterWidth: CGFloat = max(320.0, min(375.0, floor(layout.size.width / 3.0)))
let detailWidth: CGFloat = layout.size.width - masterWidth
if index == 0 {
return (CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: masterWidth, height: layout.size.height)), ContainerViewLayout(size: CGSize(width: masterWidth, height: layout.size.height), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver))
@ -358,10 +358,10 @@ open class NavigationController: UINavigationController, ContainableController,
if let blackout = self.masterDetailsBlackout {
let blackoutFrame: CGRect
switch blackout {
case .details:
blackoutFrame = CGRect(origin: CGPoint(x: masterData.0.maxX, y: 0.0), size: lastControllerFrameAndLayout.0.size)
case .master:
blackoutFrame = masterData.0
case .details:
blackoutFrame = CGRect(origin: CGPoint(x: masterData.0.maxX, y: 0.0), size: lastControllerFrameAndLayout.0.size)
case .master:
blackoutFrame = masterData.0
}
if self.controllerView.masterDetailsBlackout == nil {
self.controllerView.masterDetailsBlackout = ASDisplayNode()

View File

@ -37,6 +37,7 @@ public final class PresentationContext {
weak var volumeControlStatusBarNodeView: UIView?
var updateIsInteractionBlocked: ((Bool) -> Void)?
var updateHasBlocked: ((Bool) -> Void)?
var updateHasOpaqueOverlay: ((Bool) -> Void)?
private(set) var hasOpaqueOverlay: Bool = false {
@ -47,6 +48,9 @@ public final class PresentationContext {
}
}
private var modalPresentationValue: CGFloat = 0.0
var updateModalTransition: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
private var layout: ContainerViewLayout?
private var ready: Bool {
@ -120,6 +124,20 @@ public final class PresentationContext {
}
}
private func layoutForController(containerLayout: ContainerViewLayout, controller: ContainableController) -> (ContainerViewLayout, CGRect) {
if controller.isModalWhenInOverlay, case .regular = containerLayout.metrics.widthClass {
let topInset = (containerLayout.statusBarHeight ?? 0.0) + 20.0
var updatedLayout = containerLayout
updatedLayout.statusBarHeight = nil
updatedLayout.size = CGSize(width: min(containerLayout.size.width - 90.0, 750.0), height: min(containerLayout.size.height - 90.0, 940.0))
updatedLayout.safeInsets = UIEdgeInsets()
updatedLayout.intrinsicInsets = UIEdgeInsets()
return (updatedLayout, CGRect(origin: CGPoint(x: (containerLayout.size.width - updatedLayout.size.width) / 2.0, y: (containerLayout.size.height - updatedLayout.size.height) / 2.0), size: updatedLayout.size))
} else {
return (containerLayout, CGRect(origin: CGPoint(), size: containerLayout.size))
}
}
public func present(_ controller: ContainableController, on level: PresentationSurfaceLevel, blockInteraction: Bool = false, completion: @escaping () -> Void) {
let controllerReady = controller.ready.get()
|> filter({ $0 })
@ -140,8 +158,9 @@ public final class PresentationContext {
controller.supportedOrientations = ViewControllerSupportedOrientations(regularSize: orientations, compactSize: orientations)
}
}
controller.view.frame = CGRect(origin: CGPoint(), size: initialLayout.size)
controller.containerLayoutUpdated(initialLayout, transition: .immediate)
let (controllerLayout, controllerFrame) = self.layoutForController(containerLayout: initialLayout, controller: controller)
controller.view.frame = controllerFrame
controller.containerLayoutUpdated(controllerLayout, transition: .immediate)
var blockInteractionToken: Int?
if blockInteraction {
blockInteractionToken = self.addBlockInteraction()
@ -170,37 +189,32 @@ public final class PresentationContext {
}
strongSelf.controllers.insert((controller, level), at: insertIndex ?? strongSelf.controllers.count)
if let view = strongSelf.view, let layout = strongSelf.layout {
let (updatedControllerLayout, updatedControllerFrame) = strongSelf.layoutForController(containerLayout: layout, controller: controller)
(controller as? UIViewController)?.navigation_setDismiss({ [weak controller] in
if let strongSelf = self, let controller = controller {
strongSelf.dismiss(controller)
}
}, rootController: nil)
(controller as? UIViewController)?.setIgnoreAppearanceMethodInvocations(true)
if layout != initialLayout {
controller.view.frame = CGRect(origin: CGPoint(), size: layout.size)
if updatedControllerLayout != controllerLayout {
controller.view.frame = updatedControllerFrame
if let topLevelSubview = strongSelf.topLevelSubview(for: level) {
view.insertSubview(controller.view, belowSubview: topLevelSubview)
} else {
if let volumeControlStatusBarNodeView = strongSelf.volumeControlStatusBarNodeView {
view.insertSubview(controller.view, belowSubview: volumeControlStatusBarNodeView)
} else {
view.addSubview(controller.view)
}
view.addSubview(controller.view)
}
controller.containerLayoutUpdated(layout, transition: .immediate)
controller.containerLayoutUpdated(updatedControllerLayout, transition: .immediate)
} else {
if let topLevelSubview = strongSelf.topLevelSubview(for: level) {
view.insertSubview(controller.view, belowSubview: topLevelSubview)
} else {
if let volumeControlStatusBarNodeView = strongSelf.volumeControlStatusBarNodeView {
view.insertSubview(controller.view, belowSubview: volumeControlStatusBarNodeView)
} else {
view.addSubview(controller.view)
}
view.addSubview(controller.view)
}
}
(controller as? UIViewController)?.setIgnoreAppearanceMethodInvocations(false)
view.layer.invalidateUpTheTree()
strongSelf.updateViews()
controller.viewWillAppear(false)
if let controller = controller as? PresentableController {
controller.viewDidAppear(completion: { [weak self] in
@ -210,8 +224,18 @@ public final class PresentationContext {
controller.viewDidAppear(false)
strongSelf.notifyAccessibilityScreenChanged()
}
if controller.isModalWhenInOverlay, case .regular = layout.metrics.widthClass {
let springDuration: Double = 0.52
let springDamping: CGFloat = 110.0
controller.view.layer.animateSpring(from: NSValue(cgPoint: CGPoint(x: 0.0, y: layout.size.height - controllerFrame.minY)), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true)
strongSelf.dimView?.frame = CGRect(origin: CGPoint(), size: layout.size)
strongSelf.dimView?.alpha = 1.0
strongSelf.dimView?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
}
strongSelf.updateViews()
}
}))
} else {
@ -225,12 +249,29 @@ public final class PresentationContext {
}
private func dismiss(_ controller: ContainableController) {
if let index = self.controllers.index(where: { $0.0 === controller }) {
if let index = self.controllers.firstIndex(where: { $0.0 === controller }) {
self.controllers.remove(at: index)
controller.viewWillDisappear(false)
controller.view.removeFromSuperview()
controller.viewDidDisappear(false)
self.updateViews()
if controller.isModalWhenInOverlay, let layout = self.layout, case .regular = layout.metrics.widthClass {
let (controllerLayout, controllerFrame) = self.layoutForController(containerLayout: layout, controller: controller)
let springDuration: Double = 0.52
let springDamping: CGFloat = 110.0
controller.view.layer.animateSpring(from: NSValue(cgPoint: CGPoint()), to: NSValue(cgPoint: CGPoint(x: 0.0, y: layout.size.height - controllerFrame.minY)), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, removeOnCompletion: false, additive: true, completion: { finished in
controller.viewWillDisappear(false)
controller.view.removeFromSuperview()
controller.viewDidDisappear(false)
self.updateViews()
})
} else {
controller.viewWillDisappear(false)
controller.view.removeFromSuperview()
controller.viewDidDisappear(false)
self.updateViews()
}
let previousAlpha = self.dimView?.alpha ?? 0.0
self.dimView?.alpha = 0.0
self.dimView?.layer.animateAlpha(from: previousAlpha, to: 0.0, duration: 0.2)
}
}
@ -241,8 +282,11 @@ public final class PresentationContext {
if wasReady != self.ready {
self.readyChanged(wasReady: wasReady)
} else if self.ready {
self.dimView?.frame = CGRect(origin: CGPoint(), size: layout.size)
for (controller, _) in self.controllers {
controller.containerLayoutUpdated(layout, transition: transition)
let (controllerLayout, controllerFrame) = self.layoutForController(containerLayout: layout, controller: controller)
controller.view.frame = controllerFrame
controller.containerLayoutUpdated(controllerLayout, transition: transition)
}
}
}
@ -255,21 +299,31 @@ public final class PresentationContext {
}
}
var dimView: UIView?
private func addViews() {
if let view = self.view, let layout = self.layout {
let dimView: UIView
if let currentDimView = self.dimView {
dimView = currentDimView
} else {
dimView = UIView()
dimView.alpha = 0.0
dimView.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.4)
self.dimView = dimView
}
view.addSubview(dimView)
for (controller, _) in self.controllers {
controller.viewWillAppear(false)
if let topLevelSubview = self.topLevelSubview {
view.insertSubview(controller.view, belowSubview: topLevelSubview)
} else {
if let volumeControlStatusBarNodeView = self.volumeControlStatusBarNodeView {
view.insertSubview(controller.view, belowSubview: volumeControlStatusBarNodeView)
} else {
view.addSubview(controller.view)
}
view.addSubview(controller.view)
}
controller.view.frame = CGRect(origin: CGPoint(), size: layout.size)
controller.containerLayoutUpdated(layout, transition: .immediate)
let (controllerLayout, controllerFrame) = self.layoutForController(containerLayout: layout, controller: controller)
controller.view.frame = controllerFrame
controller.containerLayoutUpdated(controllerLayout, transition: .immediate)
if let controller = controller as? PresentableController {
controller.viewDidAppear(completion: { [weak self] in
self?.notifyAccessibilityScreenChanged()
@ -291,10 +345,18 @@ public final class PresentationContext {
}
}
private weak var currentModalController: ContainableController?
private func updateViews() {
self.hasOpaqueOverlay = self.currentlyBlocksBackgroundWhenInOverlay
var modalController: ContainableController?
var topHasOpaque = false
for (controller, _) in self.controllers.reversed() {
if controller.isModalWhenInOverlay {
if modalController == nil {
modalController = controller
}
}
if topHasOpaque {
controller.displayNode.accessibilityElementsHidden = true
} else {
@ -304,16 +366,51 @@ public final class PresentationContext {
controller.displayNode.accessibilityElementsHidden = false
}
}
if self.currentModalController !== modalController {
if let currentModalController = self.currentModalController {
currentModalController.updateTransitionWhenPresentedAsModal = nil
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
currentModalController.displayNode.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner]
}
currentModalController.displayNode.layer.cornerRadius = 0.0
}
self.currentModalController = modalController
if let modalController = modalController {
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
if let layout = self.layout, case .regular = layout.metrics.widthClass {
modalController.displayNode.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner]
} else {
modalController.displayNode.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
}
}
modalController.displayNode.layer.cornerRadius = 10.0
modalController.updateTransitionWhenPresentedAsModal = { [weak self, weak modalController] value, transition in
guard let strongSelf = self, let modalController = modalController, modalController === strongSelf.currentModalController else {
return
}
if strongSelf.modalPresentationValue != value {
strongSelf.modalPresentationValue = value
strongSelf.updateModalTransition?(value, transition)
}
}
} else {
if self.modalPresentationValue != 0.0 {
self.modalPresentationValue = 0.0
self.updateModalTransition?(0.0, .animated(duration: 0.3, curve: .spring))
}
}
}
}
private func notifyAccessibilityScreenChanged() {
UIAccessibility.post(notification: UIAccessibility.Notification.screenChanged, argument: nil)
}
func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
func hitTest(view: UIView, point: CGPoint, with event: UIEvent?) -> UIView? {
for (controller, _) in self.controllers.reversed() {
if controller.isViewLoaded {
if let result = controller.view.hitTest(point, with: event) {
if let result = controller.view.hitTest(view.convert(point, to: controller.view), with: event) {
return result
}
}

View File

@ -155,7 +155,6 @@ private func checkIsPreviewingView(_ view: UIView) -> Bool {
private func applyThemeToPreviewingView(_ view: UIView, accentColor: UIColor, darkBlur: Bool) {
if let previewingActionGroupClass = previewingActionGroupClass, view.isKind(of: previewingActionGroupClass) {
view.tintColor = accentColor
testZoomBlurEffect((view.superview?.superview?.subviews[1] as? UIVisualEffectView)?.effect)
if darkBlur {
applyThemeToPreviewingEffectView(view)
}
@ -665,7 +664,7 @@ public class Window1 {
}
}
if let result = self.presentationContext.hitTest(point, with: event) {
if let result = self.presentationContext.hitTest(view: self.hostView.containerView, point: point, with: event) {
return result
}
return self.viewController?.view.hitTest(point, with: event)

View File

@ -415,9 +415,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
func setMessage(_ message: Message) {
self.currentMessage = message
self.actionButton.isHidden = message.containsSecretMedia || Namespaces.Message.allScheduled.contains(message.id.namespace)
let canDelete: Bool
var canShare = !message.containsSecretMedia && !Namespaces.Message.allScheduled.contains(message.id.namespace)
if let peer = message.peers[message.id.peerId] {
if peer is TelegramUser || peer is TelegramSecretChat {
canDelete = true
@ -434,6 +433,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
} else {
canDelete = false
canShare = false
}
var authorNameText: String?
@ -466,7 +466,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
messageText = galleryCaptionStringWithAppliedEntities(message.text, entities: entities)
}
if self.currentMessageText != messageText || canDelete != !self.deleteButton.isHidden || self.currentAuthorNameText != authorNameText || self.currentDateText != dateText {
self.actionButton.isHidden = message.containsSecretMedia || Namespaces.Message.allScheduled.contains(message.id.namespace)
if self.currentMessageText != messageText || canDelete != !self.deleteButton.isHidden || canShare != !self.actionButton.isHidden || self.currentAuthorNameText != authorNameText || self.currentDateText != dateText {
self.currentMessageText = messageText
if messageText.length == 0 {
@ -485,6 +488,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
self.dateNode.attributedText = NSAttributedString(string: dateText, font: dateFont, textColor: .white)
self.deleteButton.isHidden = !canDelete
self.actionButton.isHidden = !canShare
self.requestLayout?(.immediate)
}

View File

@ -402,7 +402,7 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.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)))
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight))
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight))
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight))
}

View File

@ -124,7 +124,7 @@ private func readPacketCallback(userData: UnsafeMutableRawPointer?, buffer: Unsa
let readingOffset = context.readingOffset
let readCount = max(0, min(fileSize - readingOffset, Int(bufferSize)))
let range = readingOffset ..< (readingOffset + readCount)
precondition(readCount < 1 * 1024 * 1024)
assert(readCount < 16 * 1024 * 1024)
lseek(fd, off_t(range.lowerBound), SEEK_SET)
var data = Data(count: readCount)
@ -147,7 +147,7 @@ private func readPacketCallback(userData: UnsafeMutableRawPointer?, buffer: Unsa
let readCount = max(0, min(next.size - readingOffset, Int(bufferSize)))
let range = readingOffset ..< (readingOffset + readCount)
precondition(readCount < 1 * 1024 * 1024)
assert(readCount < 16 * 1024 * 1024)
let fd = open(next.path, O_RDONLY, S_IRUSR)
if fd >= 0 {

View File

@ -461,7 +461,7 @@ private func stringForRight(strings: PresentationStrings, right: TelegramChatAdm
} else if right.contains(.canEditMessages) {
return strings.Channel_EditAdmin_PermissionEditMessages
} else if right.contains(.canDeleteMessages) {
return strings.Channel_EditAdmin_PermissionDeleteMessages
return isGroup ? strings.Channel_EditAdmin_PermissionDeleteMessages : strings.Channel_EditAdmin_PermissionDeleteMessagesOfOthers
} else if right.contains(.canBanUsers) {
return strings.Channel_EditAdmin_PermissionBanUsers
} else if right.contains(.canInviteUsers) {

View File

@ -380,7 +380,7 @@ private func channelAdminsControllerEntries(presentationData: PresentationData,
switch participant.participant {
case .creator:
canEdit = false
canOpen = false
canOpen = isGroup && peer.flags.contains(.isCreator)
case let .member(id, _, adminInfo, _, _):
if id == accountPeerId {
canEdit = false

View File

@ -718,7 +718,7 @@ public final class MessageHistoryView {
for entry in state.entries {
if mutableView.namespaces.contains(entry.message.id.namespace) {
let read: Bool
if !entry.message.flags.intersection(.IsIncomingMask).isEmpty {
if entry.message.flags.contains(.Incoming) {
read = false
} else if let readState = states[entry.message.id.peerId] {
read = readState.isOutgoingMessageIndexRead(entry.message.index)

View File

@ -50,6 +50,8 @@ public final class ThemePreviewController: ViewController {
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationTheme: self.previewTheme, presentationStrings: self.presentationData.strings))
self.isModalWhenInOverlay = true
let themeName: String
if case let .theme(theme) = source {
themeName = theme.title
@ -239,7 +241,7 @@ public final class ThemePreviewController: ViewController {
return telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager)
|> take(1)
|> mapToSignal { themes -> Signal<PresentationThemeReference, NoError> in
let similarTheme = themes.filter { $0.isCreator && $0.title == info.title }.first
let similarTheme = themes.first(where: { $0.isCreator && $0.title == info.title })
if let similarTheme = similarTheme {
return updateTheme(account: context.account, accountManager: context.sharedContext.accountManager, theme: similarTheme, title: nil, slug: nil, resource: info.resource, thumbnailData: themeThumbnailData)
|> map(Optional.init)

View File

@ -45,6 +45,8 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
private var chatNodes: [ListViewItemNode]?
private let maskNode: ASImageNode
private let separatorNode: ASDisplayNode
private let chatContainerNode: ASDisplayNode
private let instantChatBackgroundNode: WallpaperBackgroundNode
private let remoteChatBackgroundNode: TransformImageNode
@ -113,6 +115,9 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
self.maskNode.displayWithoutProcessing = true
self.maskNode.contentMode = .scaleToFill
self.separatorNode = ASDisplayNode()
self.separatorNode.backgroundColor = previewTheme.rootController.tabBar.separatorColor
super.init()
self.setViewBlock({
@ -145,6 +150,8 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
self.chatContainerNode.addSubnode(self.instantChatBackgroundNode)
self.chatContainerNode.addSubnode(self.remoteChatBackgroundNode)
self.addSubnode(self.separatorNode)
self.toolbarNode.cancel = {
dismiss()
}
@ -299,13 +306,19 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
}
func animateIn(completion: (() -> Void)? = nil) {
self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
if let (layout, _) = self.validLayout, case .compact = layout.metrics.widthClass {
self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
}
}
func animateOut(completion: (() -> Void)? = nil) {
self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { _ in
if let (layout, _) = self.validLayout, case .compact = layout.metrics.widthClass {
self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { _ in
completion?()
})
} else {
completion?()
})
}
}
private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) {
@ -350,14 +363,21 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer7.id, namespace: 0, id: 0), timestamp: timestamp - 420)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer7.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 420, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer7), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right)
let width: CGFloat
if case .regular = layout.metrics.widthClass {
width = layout.size.width / 2.0
} else {
width = layout.size.width
}
let params = ListViewItemLayoutParams(width: width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right)
if let chatNodes = self.chatNodes {
for i in 0 ..< items.count {
let itemNode = chatNodes[i]
items[i].updateNode(async: { $0() }, node: {
return itemNode
}, params: params, previousItem: i == 0 ? nil : items[i - 1], nextItem: i == (items.count - 1) ? nil : items[i + 1], animation: .None, completion: { (layout, apply) in
let nodeFrame = CGRect(origin: itemNode.frame.origin, size: CGSize(width: layout.size.width, height: layout.size.height))
let nodeFrame = CGRect(origin: itemNode.frame.origin, size: CGSize(width: width, height: layout.size.height))
itemNode.contentSize = layout.contentSize
itemNode.insets = layout.insets
@ -419,14 +439,21 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message4, theme: self.previewTheme, strings: self.presentationData.strings, wallpaper: self.previewTheme.chat.defaultWallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil))
let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right)
let width: CGFloat
if case .regular = layout.metrics.widthClass {
width = layout.size.width / 2.0
} else {
width = layout.size.width
}
let params = ListViewItemLayoutParams(width: width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right)
if let messageNodes = self.messageNodes {
for i in 0 ..< items.count {
let itemNode = messageNodes[i]
items[i].updateNode(async: { $0() }, node: {
return itemNode
}, params: params, previousItem: i == 0 ? nil : items[i - 1], nextItem: i == (items.count - 1) ? nil : items[i + 1], animation: .None, completion: { (layout, apply) in
let nodeFrame = CGRect(origin: itemNode.frame.origin, size: CGSize(width: layout.size.width, height: layout.size.height))
let nodeFrame = CGRect(origin: itemNode.frame.origin, size: CGSize(width: width, height: layout.size.height))
itemNode.contentSize = layout.contentSize
itemNode.insets = layout.insets
@ -463,23 +490,49 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
}
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
self.validLayout = (layout, navigationBarHeight)
let bounds = CGRect(origin: CGPoint(), size: layout.size)
self.scrollNode.frame = bounds
let toolbarHeight = 49.0 + layout.intrinsicInsets.bottom
self.chatListBackgroundNode.frame = CGRect(x: bounds.width, y: 0.0, width: bounds.width, height: bounds.height)
self.chatContainerNode.frame = CGRect(x: 0.0, y: 0.0, width: bounds.width, height: bounds.height)
let bottomInset: CGFloat
if case .regular = layout.metrics.widthClass {
self.chatListBackgroundNode.frame = CGRect(x: 0.0, y: 0.0, width: bounds.width / 2.0, height: bounds.height)
self.chatContainerNode.frame = CGRect(x: bounds.width / 2.0, y: 0.0, width: bounds.width / 2.0, height: bounds.height)
self.scrollNode.view.contentSize = CGSize(width: bounds.width, height: bounds.height)
self.pageControlNode.isHidden = true
self.pageControlBackgroundNode.isHidden = true
self.separatorNode.isHidden = false
self.separatorNode.frame = CGRect(x: bounds.width / 2.0, y: 0.0, width: UIScreenPixel, height: bounds.height - toolbarHeight)
bottomInset = 0.0
} else {
self.chatListBackgroundNode.frame = CGRect(x: bounds.width, y: 0.0, width: bounds.width, height: bounds.height)
self.chatContainerNode.frame = CGRect(x: 0.0, y: 0.0, width: bounds.width, height: bounds.height)
self.scrollNode.view.contentSize = CGSize(width: bounds.width * 2.0, height: bounds.height)
self.pageControlNode.isHidden = false
self.pageControlBackgroundNode.isHidden = false
self.separatorNode.isHidden = true
bottomInset = 66.0
}
self.instantChatBackgroundNode.frame = self.chatContainerNode.bounds
self.remoteChatBackgroundNode.frame = self.chatContainerNode.bounds
self.blurredNode.frame = self.chatContainerNode.bounds
self.scrollNode.view.contentSize = CGSize(width: bounds.width * 2.0, height: bounds.height)
transition.updateFrame(node: self.toolbarNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - toolbarHeight), 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)
self.updateChatsLayout(layout: layout, topInset: navigationBarHeight, transition: transition)
self.updateMessagesLayout(layout: layout, bottomInset: self.isPreview ? 0.0 : (toolbarHeight + 66.0), transition: transition)
self.updateMessagesLayout(layout: layout, bottomInset: self.isPreview ? 0.0 : (toolbarHeight + bottomInset), transition: transition)
let pageControlSize = self.pageControlNode.measure(CGSize(width: bounds.width, height: 100.0))
let pageControlFrame = CGRect(origin: CGPoint(x: floor((bounds.width - pageControlSize.width) / 2.0), y: layout.size.height - toolbarHeight - 42.0), size: pageControlSize)

View File

@ -576,7 +576,7 @@ public func actualizedTheme(account: Account, accountManager: AccountManager, th
}
}
|> map { themes -> TelegramTheme in
let updatedTheme = themes.filter { $0.id == theme.id }.first
let updatedTheme = themes.first(where: { $0.id == theme.id })
if let updatedTheme = updatedTheme {
if !areThemesEqual(updatedTheme, currentTheme) {
currentTheme = updatedTheme

View File

@ -120,7 +120,7 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
itemDestructiveColor: destructiveColor,
itemPlaceholderTextColor: UIColor(rgb: 0xc8c8ce),
itemBlocksBackgroundColor: .white,
itemHighlightedBackgroundColor: UIColor(rgb: 0xd9d9d9),
itemHighlightedBackgroundColor: UIColor(rgb: 0xe5e5ea),
itemBlocksSeparatorColor: UIColor(rgb: 0xc8c7cc),
itemPlainSeparatorColor: UIColor(rgb: 0xc8c7cc),
disclosureArrowColor: UIColor(rgb: 0xbab9be),
@ -163,7 +163,7 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
itemSeparatorColor: UIColor(rgb: 0xc8c7cc),
itemBackgroundColor: .white,
pinnedItemBackgroundColor: UIColor(rgb: 0xf7f7f7),
itemHighlightedBackgroundColor: UIColor(rgb: 0xd9d9d9),
itemHighlightedBackgroundColor: UIColor(rgb: 0xe5e5ea),
itemSelectedBackgroundColor: UIColor(rgb: 0xe9f0fa),
titleColor: .black,
secretTitleColor: secretColor,

View File

@ -520,6 +520,10 @@ public func updatedPresentationData(accountManager: AccountManager, applicationI
switch effectiveChatWallpaper {
case .builtin, .color:
effectiveChatWallpaper = themeValue.chat.defaultWallpaper
case let .file(file):
if file.isPattern {
effectiveChatWallpaper = themeValue.chat.defaultWallpaper
}
default:
break
}

View File

@ -484,7 +484,7 @@ final class SharedApplicationContext {
return UIApplication.shared.open(parsedUrl, options: [UIApplication.OpenExternalURLOptionsKey.universalLinksOnly: true as NSNumber], completionHandler: { value in
completion.completion(value)
})
} else if let escapedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let parsedUrl = URL(string: escapedUrl) {
} else if let escapedUrl = (url.removingPercentEncoding ?? url).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let parsedUrl = URL(string: escapedUrl) {
return UIApplication.shared.open(parsedUrl, options: [UIApplication.OpenExternalURLOptionsKey.universalLinksOnly: true as NSNumber], completionHandler: { value in
completion.completion(value)
})

View File

@ -1585,7 +1585,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
}
func sendButtonFrame() -> CGRect? {
if let frame = self.textInputPanelNode?.actionButtons.frame {
if let mediaPreviewNode = self.inputPanelNode as? ChatRecordingPreviewInputPanelNode {
return mediaPreviewNode.convert(mediaPreviewNode.sendButton.frame, to: self)
} else if let frame = self.textInputPanelNode?.actionButtons.frame {
return self.textInputPanelNode?.convert(frame, to: self)
} else {
return nil

View File

@ -44,7 +44,7 @@ class ChatHoleItemNode: ListViewItemNode {
let backgroundNode: ASImageNode
let labelNode: TextNode
private let layoutConstants = ChatMessageItemLayoutConstants()
private let layoutConstants = ChatMessageItemLayoutConstants.default
init() {
self.backgroundNode = ASImageNode()

View File

@ -36,7 +36,7 @@ private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: LimitsCo
if let peer = message.peers[message.id.peerId], let channel = peer as? TelegramChannel {
switch channel.info {
case .broadcast:
if message.author?.id == message.id.peerId || channel.hasPermission(.editAllMessages) {
if channel.hasPermission(.editAllMessages) || !message.flags.contains(.Incoming) {
hasEditRights = true
}
default:
@ -53,7 +53,7 @@ private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: LimitsCo
if let peer = peer as? TelegramChannel {
switch peer.info {
case .broadcast:
if peer.hasPermission(.editAllMessages) {
if peer.hasPermission(.editAllMessages) || !message.flags.contains(.Incoming) {
hasEditRights = true
}
case .group:

View File

@ -339,6 +339,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
let currentItem = self.item
return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in
let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params)
let incoming = item.message.effectivelyIncoming(item.context.account.peerId)
var imageSize: CGSize = CGSize(width: 200.0, height: 200.0)
var isEmoji = false

View File

@ -590,6 +590,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
let weakSelf = Weak(self)
return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in
let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params)
return ChatMessageBubbleItemNode.beginLayout(selfReference: weakSelf, item, params, mergedTop, mergedBottom, dateHeaderAtBottom,
currentContentClassesPropertiesAndLayouts: currentContentClassesPropertiesAndLayouts,
authorNameLayout: authorNameLayout,

View File

@ -113,6 +113,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView {
let currentForwardInfo = self.appliedForwardInfo
return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in
let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params)
let incoming = item.message.effectivelyIncoming(item.context.account.peerId)
let avatarInset: CGFloat

View File

@ -78,17 +78,40 @@ struct ChatMessageItemLayoutConstants {
let instantVideo: ChatMessageItemInstantVideoConstants
let wallpapers: ChatMessageItemWallpaperLayoutConstants
init() {
self.avatarDiameter = 37.0
self.timestampHeaderHeight = 34.0
static var `default`: ChatMessageItemLayoutConstants {
return self.compact
}
fileprivate static var compact: ChatMessageItemLayoutConstants {
let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 1.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.85), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0 - UIScreenPixel, left: 1.0 - UIScreenPixel, bottom: 1.0 - UIScreenPixel, right: 1.0 - UIScreenPixel))
let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0))
let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 1.0 + UIScreenPixel, left: 1.0 + UIScreenPixel, bottom: 1.0 + UIScreenPixel, right: 1.0 + UIScreenPixel), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 17.0, mergedCornerRadius: 5.0, contentMergedCornerRadius: 5.0, maxDimensions: CGSize(width: 300.0, height: 300.0), minDimensions: CGSize(width: 170.0, height: 74.0))
let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0)
let file = ChatMessageItemFileLayoutConstants(bubbleInsets: UIEdgeInsets(top: 15.0, left: 9.0, bottom: 15.0, right: 12.0))
let instantVideo = ChatMessageItemInstantVideoConstants(insets: UIEdgeInsets(top: 4.0, left: 0.0, bottom: 4.0, right: 0.0), dimensions: CGSize(width: 212.0, height: 212.0))
let wallpapers = ChatMessageItemWallpaperLayoutConstants(maxTextWidth: 180.0)
self.bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 1.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.85), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0 - UIScreenPixel, left: 1.0 - UIScreenPixel, bottom: 1.0 - UIScreenPixel, right: 1.0 - UIScreenPixel))
self.text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0))
self.image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 1.0 + UIScreenPixel, left: 1.0 + UIScreenPixel, bottom: 1.0 + UIScreenPixel, right: 1.0 + UIScreenPixel), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 17.0, mergedCornerRadius: 5.0, contentMergedCornerRadius: 5.0, maxDimensions: CGSize(width: 300.0, height: 300.0), minDimensions: CGSize(width: 170.0, height: 74.0))
self.video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0)
self.file = ChatMessageItemFileLayoutConstants(bubbleInsets: UIEdgeInsets(top: 15.0, left: 9.0, bottom: 15.0, right: 12.0))
self.instantVideo = ChatMessageItemInstantVideoConstants(insets: UIEdgeInsets(top: 4.0, left: 0.0, bottom: 4.0, right: 0.0), dimensions: CGSize(width: 212.0, height: 212.0))
self.wallpapers = ChatMessageItemWallpaperLayoutConstants(maxTextWidth: 180.0)
return ChatMessageItemLayoutConstants(avatarDiameter: 37.0, timestampHeaderHeight: 34.0, bubble: bubble, image: image, video: video, text: text, file: file, instantVideo: instantVideo, wallpapers: wallpapers)
}
fileprivate static var regular: ChatMessageItemLayoutConstants {
let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 1.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.65), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0 - UIScreenPixel, left: 1.0 - UIScreenPixel, bottom: 1.0 - UIScreenPixel, right: 1.0 - UIScreenPixel))
let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0))
let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 1.0 + UIScreenPixel, left: 1.0 + UIScreenPixel, bottom: 1.0 + UIScreenPixel, right: 1.0 + UIScreenPixel), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 17.0, mergedCornerRadius: 5.0, contentMergedCornerRadius: 5.0, maxDimensions: CGSize(width: 440.0, height: 440.0), minDimensions: CGSize(width: 170.0, height: 74.0))
let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0)
let file = ChatMessageItemFileLayoutConstants(bubbleInsets: UIEdgeInsets(top: 15.0, left: 9.0, bottom: 15.0, right: 12.0))
let instantVideo = ChatMessageItemInstantVideoConstants(insets: UIEdgeInsets(top: 4.0, left: 0.0, bottom: 4.0, right: 0.0), dimensions: CGSize(width: 212.0, height: 212.0))
let wallpapers = ChatMessageItemWallpaperLayoutConstants(maxTextWidth: 180.0)
return ChatMessageItemLayoutConstants(avatarDiameter: 37.0, timestampHeaderHeight: 34.0, bubble: bubble, image: image, video: video, text: text, file: file, instantVideo: instantVideo, wallpapers: wallpapers)
}
}
func chatMessageItemLayoutConstants(_ constants: (ChatMessageItemLayoutConstants, ChatMessageItemLayoutConstants), params: ListViewItemLayoutParams) -> ChatMessageItemLayoutConstants {
if params.width > 680.0 {
return constants.1
} else {
return constants.0
}
}
@ -97,8 +120,6 @@ enum ChatMessageItemBottomNeighbor {
case merged(semi: Bool)
}
let defaultChatMessageItemLayoutConstants = ChatMessageItemLayoutConstants()
enum ChatMessagePeekPreviewContent {
case media(Media)
case url(ASDisplayNode, CGRect, String, Bool)
@ -607,7 +628,7 @@ final class ChatMessageAccessibilityData {
}
public class ChatMessageItemView: ListViewItemNode {
let layoutConstants = defaultChatMessageItemLayoutConstants
let layoutConstants = (ChatMessageItemLayoutConstants.compact, ChatMessageItemLayoutConstants.regular)
var item: ChatMessageItem?
var accessibilityData: ChatMessageAccessibilityData?

View File

@ -141,6 +141,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
let currentItem = self.item
return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in
let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params)
let incoming = item.message.effectivelyIncoming(item.context.account.peerId)
var imageSize: CGSize = CGSize(width: 100.0, height: 100.0)
if let telegramFile = telegramFile {

View File

@ -670,7 +670,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
order = [
(.canChangeInfo, self.presentationData.strings.Channel_AdminLog_CanChangeInfo),
(.canPostMessages, self.presentationData.strings.Channel_AdminLog_CanSendMessages),
(.canDeleteMessages, self.presentationData.strings.Channel_AdminLog_CanDeleteMessages),
(.canDeleteMessages, self.presentationData.strings.Channel_AdminLog_CanDeleteMessagesOfOthers),
(.canEditMessages, self.presentationData.strings.Channel_AdminLog_CanEditMessages),
(.canInviteUsers, self.presentationData.strings.Channel_AdminLog_CanInviteUsers),
(.canPinMessages, self.presentationData.strings.Channel_AdminLog_CanPinMessages),

View File

@ -19,7 +19,7 @@ private func generatePlayIcon(_ theme: PresentationTheme) -> UIImage? {
final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
private let deleteButton: HighlightableButtonNode
private let sendButton: HighlightableButtonNode
let sendButton: HighlightTrackingButtonNode
private var sendButtonRadialStatusNode: ChatSendButtonRadialStatusNode?
private let playButton: HighlightableButtonNode
private let pauseButton: HighlightableButtonNode
@ -42,7 +42,7 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
self.deleteButton.displaysAsynchronously = false
self.deleteButton.setImage(generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionTrash"), color: theme.chat.inputPanel.panelControlAccentColor), for: [])
self.sendButton = HighlightableButtonNode()
self.sendButton = HighlightTrackingButtonNode()
self.sendButton.displaysAsynchronously = false
self.sendButton.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(theme), for: [])
@ -87,6 +87,16 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
self.addSubnode(self.durationLabel)
self.addSubnode(self.waveformButton)
self.sendButton.highligthedChanged = { [weak self] highlighted in
if let strongSelf = self {
if highlighted {
strongSelf.sendButton.layer.animateScale(from: 1.0, to: 0.75, duration: 0.4, removeOnCompletion: false)
} else if let presentationLayer = strongSelf.sendButton.layer.presentation() {
strongSelf.sendButton.layer.animateScale(from: CGFloat((presentationLayer.value(forKeyPath: "transform.scale.y") as? NSNumber)?.floatValue ?? 1.0), to: 1.0, duration: 0.25, removeOnCompletion: false)
}
}
}
self.deleteButton.addTarget(self, action: #selector(self.deletePressed), forControlEvents: [.touchUpInside])
self.sendButton.addTarget(self, action: #selector(self.sendPressed), forControlEvents: [.touchUpInside])
@ -98,8 +108,18 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
self.statusDisposable.dispose()
}
@objc func buttonPressed() {
self.interfaceInteraction?.deleteChat()
override func didLoad() {
super.didLoad()
let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongPress(_:)))
gestureRecognizer.minimumPressDuration = 0.4
self.sendButton.view.addGestureRecognizer(gestureRecognizer)
}
@objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
if gestureRecognizer.state == .began {
self.interfaceInteraction?.displaySendMessageOptions()
}
}
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {

View File

@ -61,7 +61,7 @@ class ChatUnreadItemNode: ListViewItemNode {
private var theme: ChatPresentationThemeData?
private let layoutConstants = ChatMessageItemLayoutConstants()
private let layoutConstants = ChatMessageItemLayoutConstants.default
init() {
self.backgroundNode = ASImageNode()

View File

@ -44,7 +44,11 @@ public class ComposeController: ViewController {
self.title = self.presentationData.strings.Compose_NewMessage
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
self.isModalWhenInOverlay = true
//self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(cancelPressed))
self.scrollToTop = { [weak self] in
if let strongSelf = self {
@ -257,4 +261,8 @@ public class ComposeController: ViewController {
private func openPeer(peerId: PeerId) {
(self.navigationController as? NavigationController)?.replaceTopController(ChatControllerImpl(context: self.context, chatLocation: .peer(peerId)), animated: true)
}
@objc private func cancelPressed() {
self.presentingViewController?.dismiss(animated: true, completion: nil)
}
}

View File

@ -273,7 +273,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
}
}))
} else {
subscriber.putError(.generic)
subscriber.putError(.unsupported)
}
return disposables

View File

@ -414,6 +414,6 @@ final class VerticalListContextResultsChatInputPanelItemNode: ListViewItemNode {
guard let item = self.item else {
return
}
item.resultSelected(item.result, self, self.bounds)
let _ = item.resultSelected(item.result, self, self.bounds)
}
}

View File

@ -63,7 +63,7 @@
NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath];
NSDictionary *JSONObject = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData
options:0 error:&error] : nil;
if (JSONObject && !error) {
if (JSONObject && [JSONObject isKindOfClass:[NSDictionary class]] && !error) {
LOTComposition *laScene = [[self alloc] initWithJSON:JSONObject withAssetBundle:[NSBundle mainBundle]];
laScene.rootDirectory = [filePath stringByDeletingLastPathComponent];
[[LOTAnimationCache sharedCache] addAnimation:laScene forKey:animationName];