Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2021-06-17 16:23:08 +03:00
commit 0e225c0226
15 changed files with 151 additions and 32 deletions

View File

@ -1721,7 +1721,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
})
}
let mediaAccessoryPanel = MediaNavigationAccessoryPanel(context: self.context)
let mediaAccessoryPanel = MediaNavigationAccessoryPanel(context: self.context, displayBackground: true)
mediaAccessoryPanel.containerNode.headerNode.displayScrubber = item.playbackData?.type != .instantVideo
mediaAccessoryPanel.close = { [weak self] in
if let strongSelf = self, let (_, _, _, _, type, _) = strongSelf.playlistStateAndType {

View File

@ -450,6 +450,9 @@ public class DrawingContext {
}
public init(size: CGSize, scale: CGFloat = 0.0, opaque: Bool = false, clear: Bool = false) {
assert(!size.width.isZero && !size.height.isZero)
let size: CGSize = CGSize(width: max(1.0, size.width), height: max(1.0, size.height))
let actualScale: CGFloat
if scale.isZero {
actualScale = deviceScale

View File

@ -70,6 +70,9 @@ typedef enum
if (self != nil)
{
_allowsTrimming = true;
self.clipsToBounds = true;
self.layer.cornerRadius = 16.0f;
_wrapperView = [[UIControl alloc] initWithFrame:CGRectMake(0, 0, 0, 33)];
_wrapperView.hitTestEdgeInsets = UIEdgeInsetsMake(-5, -10, -5, -10);

View File

@ -121,22 +121,28 @@ public final class CachedPatternWallpaperMaskRepresentation: CachedMediaResource
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
public let size: CGSize?
public let scaleFromCenter: CGFloat?
public var uniqueId: String {
if let size = self.size {
return "pattern-wallpaper-mask-\(Int(size.width))x\(Int(size.height))"
var result = "pattern-wallpaper-mask-\(Int(size.width))x\(Int(size.height))"
if let scaleFromCenter = self.scaleFromCenter {
result.append("-scale\(scaleFromCenter)")
}
return result
} else {
return "pattern-wallpaper-mask"
}
}
public init(size: CGSize?) {
public init(size: CGSize?, scaleFromCenter: CGFloat?) {
self.size = size
self.scaleFromCenter = scaleFromCenter
}
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
if let to = to as? CachedPatternWallpaperMaskRepresentation {
return self.size == to.size
return self.size == to.size && self.scaleFromCenter == to.scaleFromCenter
} else {
return false
}

View File

@ -411,6 +411,10 @@ final class ThemeGridControllerNode: ASDisplayNode {
}
}
}
/*if !entries.isEmpty {
entries = [entries[0]]
}*/
let previous = previousEntries.swap(entries)
return (preparedThemeGridEntryTransition(context: context, from: previous ?? [], to: entries, interaction: interaction), previous == nil)

View File

@ -330,6 +330,11 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
self.patternButtonNode.isSelected = false
self.playButtonNode.setImage(self.playButtonRotateImage, for: [])
}
case .asset:
self.nativeNode._internalUpdateIsSettingUpWallpaper()
self.nativeNode.isHidden = true
self.patternButtonNode.isSelected = false
self.playButtonNode.setImage(self.playButtonRotateImage, for: [])
default:
self.nativeNode.isHidden = true
self.patternButtonNode.isSelected = false
@ -851,7 +856,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
let dimensions = file.file.dimensions ?? PixelDimensions(width: 1440, height: 2960)
let size = dimensions.cgSize.fitted(CGSize(width: 1280.0, height: 1280.0))
let _ = self.context.account.postbox.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: true).start()
let _ = self.context.account.postbox.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: nil), complete: false, fetch: true).start()
}
}

View File

@ -4,6 +4,6 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *backgroundColor, UIColor *foregroundColor);
UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *backgroundColor, UIColor *foregroundColor, CGFloat scaleFromCenter);
#endif /* Lottie_h */

View File

@ -83,7 +83,7 @@ CGSize aspectFillSize(CGSize size, CGSize bounds) {
@end
UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *backgroundColor, UIColor *foregroundColor) {
UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *backgroundColor, UIColor *foregroundColor, CGFloat scaleFromCenter) {
NSDate *startTime = [NSDate date];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
@ -104,9 +104,9 @@ UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *b
[xmlString replaceOccurrencesOfString:[NSString stringWithFormat:@"class=\"%@\"", styleName] withString:[NSString stringWithFormat:@"style=\"%@\"", styleValue] options:0 range:NSMakeRange(0, xmlString.length)];
}
char *zeroTerminatedData = xmlString.UTF8String;
const char *zeroTerminatedData = xmlString.UTF8String;
NSVGimage *image = nsvgParse(zeroTerminatedData, "px", 96);
NSVGimage *image = nsvgParse((char *)zeroTerminatedData, "px", 96);
if (image == nil || image->width < 1.0f || image->height < 1.0f) {
return nil;
}
@ -128,6 +128,10 @@ UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *b
CGContextScaleCTM(context, scale, scale);
CGContextTranslateCTM(context, (size.width - drawingSize.width) / 2.0, (size.height - drawingSize.height) / 2.0);
CGContextTranslateCTM(context, size.width / 2.0f, size.height / 2.0f);
CGContextScaleCTM(context, scaleFromCenter, scaleFromCenter);
CGContextTranslateCTM(context, -size.width / 2.0f, -size.height / 2.0f);
for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
if (!(shape->flags & NSVG_FLAGS_VISIBLE)) {
@ -135,7 +139,6 @@ UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *b
}
if (shape->fill.type != NSVG_PAINT_NONE) {
//CGContextSetFillColorWithColor(context, UIColorRGBA(shape->fill.color, shape->opacity).CGColor);
CGContextSetFillColorWithColor(context, [foregroundColor colorWithAlphaComponent:shape->opacity].CGColor);
bool isFirst = true;
@ -173,7 +176,6 @@ UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *b
}
if (shape->stroke.type != NSVG_PAINT_NONE) {
//CGContextSetStrokeColorWithColor(context, UIColorRGBA(shape->fill.color, shape->opacity).CGColor);
CGContextSetStrokeColorWithColor(context, [foregroundColor colorWithAlphaComponent:shape->opacity].CGColor);
CGContextSetMiterLimit(context, shape->miterLimit);
@ -196,10 +198,10 @@ UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *b
CGContextSetLineJoin(context, kCGLineJoinBevel);
break;
case NSVG_JOIN_MITER:
CGContextSetLineCap(context, kCGLineJoinMiter);
CGContextSetLineJoin(context, kCGLineJoinMiter);
break;
case NSVG_JOIN_ROUND:
CGContextSetLineCap(context, kCGLineJoinRound);
CGContextSetLineJoin(context, kCGLineJoinRound);
break;
default:
break;

View File

@ -8,22 +8,33 @@ import TelegramPresentationData
import AccountContext
public final class MediaNavigationAccessoryContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
private let displayBackground: Bool
public let backgroundNode: ASDisplayNode
public let separatorNode: ASDisplayNode
public let headerNode: MediaNavigationAccessoryHeaderNode
private let currentHeaderHeight: CGFloat = MediaNavigationAccessoryHeaderNode.minimizedHeight
private var presentationData: PresentationData
init(context: AccountContext) {
init(context: AccountContext, displayBackground: Bool) {
self.displayBackground = displayBackground
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.backgroundNode = ASDisplayNode()
self.separatorNode = ASDisplayNode()
self.headerNode = MediaNavigationAccessoryHeaderNode(presentationData: self.presentationData)
super.init()
if self.displayBackground {
self.backgroundNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.opaqueBackgroundColor
self.separatorNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.separatorColor
}
self.addSubnode(self.backgroundNode)
self.addSubnode(self.separatorNode)
self.addSubnode(self.headerNode)
}
@ -31,6 +42,11 @@ public final class MediaNavigationAccessoryContainerNode: ASDisplayNode, UIGestu
func updatePresentationData(_ presentationData: PresentationData) {
self.presentationData = presentationData
if self.displayBackground {
self.backgroundNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.opaqueBackgroundColor
self.separatorNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.separatorColor
}
self.headerNode.updatePresentationData(presentationData)
}
@ -44,6 +60,7 @@ public final class MediaNavigationAccessoryContainerNode: ASDisplayNode, UIGestu
func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) {
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: self.currentHeaderHeight)))
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.currentHeaderHeight - UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel)))
let headerHeight = self.currentHeaderHeight
transition.updateFrame(node: self.headerNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: headerHeight)))

View File

@ -16,8 +16,8 @@ public final class MediaNavigationAccessoryPanel: ASDisplayNode {
public var playPrevious: (() -> Void)?
public var playNext: (() -> Void)?
public init(context: AccountContext) {
self.containerNode = MediaNavigationAccessoryContainerNode(context: context)
public init(context: AccountContext, displayBackground: Bool = false) {
self.containerNode = MediaNavigationAccessoryContainerNode(context: context, displayBackground: displayBackground)
super.init()

View File

@ -67,6 +67,10 @@ import Speak
import UniversalMediaPlayer
import WallpaperBackgroundNode
#if DEBUG
import os.signpost
#endif
extension ChatLocation {
var peerId: PeerId {
switch self {
@ -175,6 +179,37 @@ enum ChatLoadingMessageSubject {
case pinnedMessage
}
#if DEBUG
private final class SignpostData {
@available(iOSApplicationExtension 12.0, iOS 12.0, *)
final class Impl {
let signpostLog: OSLog
let signpostId: OSSignpostID
init() {
self.signpostLog = OSLog(
subsystem: "org.telegram.Telegram-iOS",
category: "ChatAppear"
)
self.signpostId = OSSignpostID(log: self.signpostLog)
}
}
private static var _impl: AnyObject? = {
if #available(iOSApplicationExtension 12.0, iOS 12.0, *) {
return Impl()
} else {
return nil
}
}()
@available(iOSApplicationExtension 12.0, iOS 12.0, *)
static var impl: Impl {
return self._impl! as! Impl
}
}
#endif
public final class ChatControllerImpl: TelegramBaseController, ChatController, GalleryHiddenMediaTarget, UIDropInteractionDelegate {
private var validLayout: ContainerViewLayout?
@ -6935,6 +6970,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
override public func viewWillAppear(_ animated: Bool) {
#if DEBUG
if #available(iOSApplicationExtension 12.0, iOS 12.0, *) {
os_signpost(
.begin,
log: SignpostData.impl.signpostLog,
name: "Appear",
signpostID: SignpostData.impl.signpostId
)
}
#endif
super.viewWillAppear(animated)
if self.willAppear {
@ -6958,6 +7004,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
override public func viewDidAppear(_ animated: Bool) {
#if DEBUG
if #available(iOSApplicationExtension 12.0, iOS 12.0, *) {
os_signpost(
.end,
log: SignpostData.impl.signpostLog,
name: "Appear",
signpostID: SignpostData.impl.signpostId
)
}
#endif
super.viewDidAppear(animated)
self.didAppear = true

View File

@ -424,7 +424,7 @@ private func fetchCachedPatternWallpaperMaskRepresentation(resource: MediaResour
if data.count > 5, let string = String(data: data.subdata(in: 0 ..< 5), encoding: .utf8), string == "<?xml" {
let size = representation.size ?? CGSize(width: 1440.0, height: 2960.0)
if let image = drawSvgImage(data, size, .black, .white) {
if let image = drawSvgImage(data, size, .black, .white, representation.scaleFromCenter ?? 1.0) {
if let alphaDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeJPEG, 1, nil) {
CGImageDestinationSetProperties(alphaDestination, [:] as CFDictionary)
@ -490,7 +490,7 @@ private func fetchCachedPatternWallpaperRepresentation(resource: MediaResource,
if data.count > 5, let string = String(data: data.subdata(in: 0 ..< 5), encoding: .utf8), string == "<?xml" {
let defaultSize = CGSize(width: 1440.0, height: 2960.0)
size = defaultSize
if let image = drawSvgImage(data, defaultSize, .black, .white) {
if let image = drawSvgImage(data, defaultSize, .black, .white, 1.0) {
maskImage = image
}
} else if let image = UIImage(data: data) {

View File

@ -205,7 +205,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
})
}
let mediaAccessoryPanel = MediaNavigationAccessoryPanel(context: self.context)
let mediaAccessoryPanel = MediaNavigationAccessoryPanel(context: self.context, displayBackground: true)
mediaAccessoryPanel.containerNode.headerNode.displayScrubber = item.playbackData?.type != .instantVideo
mediaAccessoryPanel.close = { [weak self] in
if let strongSelf = self, let (_, _, _, _, type, _) = strongSelf.playlistStateAndType {

View File

@ -86,7 +86,9 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
return
}
if let bubbleTheme = backgroundNode.bubbleTheme, let wallpaper = backgroundNode.wallpaper, let bubbleCorners = backgroundNode.bubbleCorners {
if let bubbleTheme = backgroundNode.bubbleTheme, let bubbleCorners = backgroundNode.bubbleCorners {
let wallpaper = backgroundNode.wallpaper ?? bubbleTheme.chat.defaultWallpaper
let graphics = PresentationResourcesChat.principalGraphics(theme: bubbleTheme, wallpaper: wallpaper, bubbleCorners: bubbleCorners)
var needsCleanBackground = false
switch self.bubbleType {
@ -280,6 +282,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
private var validLayout: CGSize?
private var wallpaper: TelegramWallpaper?
private var isSettingUpWallpaper: Bool = false
private struct CachedValidPatternImage {
let generate: (TransformImageArguments) -> DrawingContext?
@ -513,6 +516,10 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
}
}
public func _internalUpdateIsSettingUpWallpaper() {
self.isSettingUpWallpaper = true
}
private func loadPatternForSizeIfNeeded(size: CGSize, transition: ContainedViewLayoutTransition) {
guard let wallpaper = self.wallpaper else {
return
@ -711,19 +718,28 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
}
public func hasBubbleBackground(for type: WallpaperBackgroundNode.BubbleBackgroundNode.BubbleType) -> Bool {
guard let bubbleTheme = self.bubbleTheme, let wallpaper = self.wallpaper, let bubbleCorners = self.bubbleCorners else {
guard let bubbleTheme = self.bubbleTheme, let bubbleCorners = self.bubbleCorners else {
return false
}
if self.wallpaper == nil && !self.isSettingUpWallpaper {
return false
}
var hasPlainWallpaper = false
switch wallpaper {
case .color:
hasPlainWallpaper = true
default:
break
let graphicsWallpaper: TelegramWallpaper
if let wallpaper = self.wallpaper {
switch wallpaper {
case .color:
hasPlainWallpaper = true
default:
break
}
graphicsWallpaper = wallpaper
} else {
graphicsWallpaper = bubbleTheme.chat.defaultWallpaper
}
let graphics = PresentationResourcesChat.principalGraphics(theme: bubbleTheme, wallpaper: wallpaper, bubbleCorners: bubbleCorners)
let graphics = PresentationResourcesChat.principalGraphics(theme: bubbleTheme, wallpaper: graphicsWallpaper, bubbleCorners: bubbleCorners)
switch type {
case .incoming:
if graphics.incomingBubbleGradientImage != nil {

View File

@ -362,13 +362,18 @@ private func patternWallpaperDatas(account: Account, accountManager: AccountMana
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
let size: CGSize?
var scaleFromCenter: CGFloat?
switch mode {
case .thumbnail:
size = largestRepresentation.dimensions.cgSize.fitted(CGSize(width: 640.0, height: 640.0))
let factor = smallestRepresentation.dimensions.cgSize.width / largestRepresentation.dimensions.cgSize.width
if smallestRepresentation.dimensions.height >= 700 && abs(factor - 1.0) <= .ulpOfOne {
scaleFromCenter = 2.1
}
default:
size = nil
}
let maybeFullSize = combineLatest(accountManager.mediaBox.cachedResourceRepresentation(largestRepresentation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: false), account.postbox.mediaBox.cachedResourceRepresentation(largestRepresentation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: false))
let maybeFullSize = combineLatest(accountManager.mediaBox.cachedResourceRepresentation(largestRepresentation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: false), account.postbox.mediaBox.cachedResourceRepresentation(largestRepresentation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: false))
let signal = maybeFullSize
|> take(1)
@ -388,12 +393,12 @@ private func patternWallpaperDatas(account: Account, accountManager: AccountMana
let thumbnailData = Signal<Data?, NoError> { subscriber in
let fetchedDisposable = fetchedThumbnail.start()
let thumbnailDisposable = account.postbox.mediaBox.cachedResourceRepresentation(representations[smallestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: true).start(next: { next in
let thumbnailDisposable = account.postbox.mediaBox.cachedResourceRepresentation(representations[smallestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: true).start(next: { next in
subscriber.putNext(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []))
if next.complete, let data = try? Data(contentsOf: URL(fileURLWithPath: next.path), options: .mappedRead) {
accountManager.mediaBox.storeResourceData(representations[smallestIndex].representation.resource.id, data: data)
let _ = accountManager.mediaBox.cachedResourceRepresentation(representations[smallestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: true).start()
let _ = accountManager.mediaBox.cachedResourceRepresentation(representations[smallestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: true).start()
}
}, error: subscriber.putError, completed: subscriber.putCompletion)
@ -405,12 +410,12 @@ private func patternWallpaperDatas(account: Account, accountManager: AccountMana
let fullSizeData = Signal<(Data?, Bool), NoError> { subscriber in
let fetchedFullSizeDisposable = fetchedFullSize.start()
let fullSizeDisposable = account.postbox.mediaBox.cachedResourceRepresentation(representations[largestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: true).start(next: { next in
let fullSizeDisposable = account.postbox.mediaBox.cachedResourceRepresentation(representations[largestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: true).start(next: { next in
subscriber.putNext((next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []), next.complete))
if next.complete, let data = try? Data(contentsOf: URL(fileURLWithPath: next.path), options: .mappedRead) {
accountManager.mediaBox.storeResourceData(representations[largestIndex].representation.resource.id, data: data)
let _ = accountManager.mediaBox.cachedResourceRepresentation(representations[largestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: true).start()
let _ = accountManager.mediaBox.cachedResourceRepresentation(representations[largestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: true).start()
}
}, error: subscriber.putError, completed: subscriber.putCompletion)
@ -535,6 +540,7 @@ public func patternWallpaperImageInternal(thumbnailData: Data?, fullSizeData: Da
let overlayImage = generateImage(arguments.drawingRect.size, rotatedContext: { size, c in
c.clear(CGRect(origin: CGPoint(), size: size))
let image = customArguments.preview ? (scaledSizeImage ?? fullSizeImage) : fullSizeImage
if let image = image {
var fittedSize = CGSize(width: image.width, height: image.height)
if abs(fittedSize.width - arguments.boundingSize.width).isLessThanOrEqualTo(CGFloat(1.0)) {