Merge commit '3ac9d2d9a41a9e15912d4aceaeec935b684400f4'

This commit is contained in:
Isaac 2025-01-29 19:26:50 +04:00
commit 47b0315671
28 changed files with 207 additions and 45 deletions

View File

@ -13798,3 +13798,6 @@ Sorry for the inconvenience.";
"NameColor.GiftTitle" = "USE A GIFT";
"NameColor.GiftInfo" = "Apply your collectible's unique look to your profile.";
"NameColor.WearCollectible" = "Wear Collectible";
"Notification.StarsGift.TransferToChannel" = "%@ transferred a unique collectible to %@";
"Notification.StarsGift.TransferToChannelYou" = "You transferred a unique collectible to %@";

View File

@ -370,7 +370,7 @@ final class BrowserAddressListComponent: Component {
if let media = message.media.first(where: { $0 is TelegramMediaWebpage }) as? TelegramMediaWebpage {
webPage = media
} else {
webPage = TelegramMediaWebpage(webpageId: MediaId(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: primaryUrl, displayUrl: "", hash: 0, type: nil, websiteName: "", title: message.text, text: "", embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, image: nil, file: nil, story: nil, attributes: [], instantPage: nil)))
webPage = TelegramMediaWebpage(webpageId: MediaId(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: primaryUrl, displayUrl: "", hash: 0, type: nil, websiteName: "", title: message.text, text: "", embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, imageIsVideoCover: false, image: nil, file: nil, story: nil, attributes: [], instantPage: nil)))
}
itemMessage = message
} else {
@ -560,7 +560,7 @@ final class BrowserAddressListComponent: Component {
component: AnyComponent(BrowserAddressListItemComponent(
context: component.context,
theme: component.theme,
webPage: TelegramMediaWebpage(webpageId: EngineMedia.Id(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: "https://telegram.org", displayUrl: "https://telegram.org", hash: 0, type: nil, websiteName: "Telegram", title: "Telegram Telegram", text: "Telegram", embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, image: nil, file: nil, story: nil, attributes: [], instantPage: nil))),
webPage: TelegramMediaWebpage(webpageId: EngineMedia.Id(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: "https://telegram.org", displayUrl: "https://telegram.org", hash: 0, type: nil, websiteName: "Telegram", title: "Telegram Telegram", text: "Telegram", embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, imageIsVideoCover: false, image: nil, file: nil, story: nil, attributes: [], instantPage: nil))),
message: nil,
hasNext: true,
insets: .zero,

View File

@ -138,6 +138,7 @@ private func parseJson(_ input: [String: Any], url: String) -> TelegramMediaWebp
duration: nil,
author: byline,
isMediaLargeByDefault: nil,
imageIsVideoCover: false,
image: nil,
file: nil,
story: nil,

View File

@ -1023,7 +1023,7 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
}
self.instantPage = webPage
self.instantPageResources = resources
let _ = (updatedRemoteWebpage(postbox: self.context.account.postbox, network: self.context.account.network, accountPeerId: self.context.account.peerId, webPage: WebpageReference(TelegramMediaWebpage(webpageId: MediaId(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: self._state.url, displayUrl: "", hash: 0, type: nil, websiteName: nil, title: nil, text: nil, embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, image: nil, file: nil, story: nil, attributes: [], instantPage: nil)))))
let _ = (updatedRemoteWebpage(postbox: self.context.account.postbox, network: self.context.account.network, accountPeerId: self.context.account.peerId, webPage: WebpageReference(TelegramMediaWebpage(webpageId: MediaId(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: self._state.url, displayUrl: "", hash: 0, type: nil, websiteName: nil, title: nil, text: nil, embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, imageIsVideoCover: false, image: nil, file: nil, story: nil, attributes: [], instantPage: nil)))))
|> deliverOnMainQueue).start(next: { [weak self] webPage in
guard let self, let webPage, case let .Loaded(result) = webPage.content, let _ = result.instantPage else {
return
@ -1518,6 +1518,7 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
duration: nil,
author: nil,
isMediaLargeByDefault: nil,
imageIsVideoCover: false,
image: image,
file: nil,
story: nil,

View File

@ -5286,7 +5286,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode {
return nil
case .links:
var media: [EngineMedia] = []
media.append(.webpage(TelegramMediaWebpage(webpageId: EngineMedia.Id(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: "https://telegram.org", displayUrl: "https://telegram.org", hash: 0, type: nil, websiteName: "Telegram", title: "Telegram Telegram", text: "Telegram", embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, image: nil, file: nil, story: nil, attributes: [], instantPage: nil)))))
media.append(.webpage(TelegramMediaWebpage(webpageId: EngineMedia.Id(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: "https://telegram.org", displayUrl: "https://telegram.org", hash: 0, type: nil, websiteName: "Telegram", title: "Telegram Telegram", text: "Telegram", embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, imageIsVideoCover: false, image: nil, file: nil, story: nil, attributes: [], instantPage: nil)))))
let message = EngineMessage(
stableId: 0,
stableVersion: 0,

View File

@ -172,8 +172,10 @@ public final class ContextControllerActionsListActionItemNode: HighlightTracking
}
if highlighted {
strongSelf.highlightBackgroundNode.alpha = 1.0
strongSelf.startTimer()
} else {
strongSelf.highlightBackgroundNode.alpha = 0.0
strongSelf.invalidateTimer()
}
}
@ -183,6 +185,25 @@ public final class ContextControllerActionsListActionItemNode: HighlightTracking
deinit {
self.iconDisposable?.dispose()
}
private var timer: SwiftSignalKit.Timer?
private func startTimer() {
self.invalidateTimer()
self.timer = SwiftSignalKit.Timer(timeout: 1.0, repeat: false, completion: { [weak self] in
guard let self else {
return
}
self.invalidateTimer()
self.longPressed()
}, queue: Queue.mainQueue())
self.timer?.start()
}
private func invalidateTimer() {
self.timer?.invalidate()
self.timer = nil
}
public override func didLoad() {
super.didLoad()
@ -191,6 +212,8 @@ public final class ContextControllerActionsListActionItemNode: HighlightTracking
}
@objc private func pressed() {
self.invalidateTimer()
self.item.action?(ContextMenuActionItem.Action(
controller: self.getController(),
dismissWithResult: { [weak self] result in
@ -208,6 +231,26 @@ public final class ContextControllerActionsListActionItemNode: HighlightTracking
))
}
private func longPressed() {
self.touchesCancelled(nil, with: nil)
self.item.longPressAction?(ContextMenuActionItem.Action(
controller: self.getController(),
dismissWithResult: { [weak self] result in
guard let strongSelf = self else {
return
}
strongSelf.requestDismiss(result)
},
updateAction: { [weak self] id, updatedAction in
guard let strongSelf = self else {
return
}
strongSelf.requestUpdateAction(id, updatedAction)
}
))
}
public func canBeHighlighted() -> Bool {
return self.item.action != nil
}

View File

@ -345,7 +345,11 @@ public class DrawingStickerEntityView: DrawingEntityView {
} else {
imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
self.addSubview(imageView)
if let _ = self.animationNode {
self.insertSubview(imageView, at: 0)
} else {
self.addSubview(imageView)
}
self.animatedImageView = imageView
}
imageView.image = image
@ -754,11 +758,16 @@ public class DrawingStickerEntityView: DrawingEntityView {
self.updateAnimationColor()
if case .message = self.stickerEntity.content, self.animatedImageView == nil {
let image = self.isNightTheme ? self.stickerEntity.secondaryRenderImage : self.stickerEntity.renderImage
if let image {
self.setupWithImage(image)
switch self.stickerEntity.content {
case .message, .gift:
if self.animatedImageView == nil {
let image = self.isNightTheme ? self.stickerEntity.secondaryRenderImage : self.stickerEntity.renderImage
if let image {
self.setupWithImage(image)
}
}
default:
break
}
self.updateMirroring(animated: animated)

View File

@ -77,7 +77,10 @@ private func mediaForMessage(message: Message) -> [(Media, TelegramMediaImage?)]
case let .Loaded(content):
if let embedUrl = content.embedUrl, !embedUrl.isEmpty {
return [(webpage, nil)]
} else if let file = content.file {
} else if var file = content.file {
if content.imageIsVideoCover, let image = content.image {
file = file.withUpdatedVideoCover(image)
}
if let result = galleryMediaForMedia(media: file) {
return [(result, content.image)]
}

View File

@ -632,7 +632,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
let frame = CGRect(origin: CGPoint(x: floor((boundingWidth - size.width) / 2.0), y: 0.0), size: size)
let item: InstantPageItem
if let url = url, let coverId = coverId, case let .image(image) = media[coverId] {
let loadedContent = TelegramMediaWebpageLoadedContent(url: url, displayUrl: url, hash: 0, type: "video", websiteName: nil, title: nil, text: nil, embedUrl: url, embedType: "video", embedSize: PixelDimensions(size), duration: nil, author: nil, isMediaLargeByDefault: nil, image: image, file: nil, story: nil, attributes: [], instantPage: nil)
let loadedContent = TelegramMediaWebpageLoadedContent(url: url, displayUrl: url, hash: 0, type: "video", websiteName: nil, title: nil, text: nil, embedUrl: url, embedType: "video", embedSize: PixelDimensions(size), duration: nil, author: nil, isMediaLargeByDefault: nil, imageIsVideoCover: false, image: image, file: nil, story: nil, attributes: [], instantPage: nil)
let content = TelegramMediaWebpageContent.Loaded(loadedContent)
item = InstantPageImageItem(frame: frame, webPage: webpage, media: InstantPageMedia(index: embedIndex, media: .webpage(TelegramMediaWebpage(webpageId: EngineMedia.Id(namespace: Namespaces.Media.LocalWebpage, id: -1), content: content)), url: nil, caption: nil, credit: nil), attributes: [], interactive: true, roundCorners: false, fit: false)

View File

@ -63,9 +63,12 @@
- (void)setFullSizeImage:(UIImage *)image forItem:(id<TGMediaEditableItem>)item;
- (SSignal *)coverImageSignalForItem:(NSObject<TGMediaEditableItem> *)item;
- (void)setCoverImage:(UIImage *)image forItem:(id<TGMediaEditableItem>)item;
- (void)setCoverImage:(UIImage *)image position:(NSNumber *)position forItem:(id<TGMediaEditableItem>)item;
- (UIImage *)coverImageForItem:(NSObject<TGMediaEditableItem> *)item;
- (NSNumber *)coverPositionForItem:(NSObject<TGMediaEditableItem> *)item;
- (void)setCoverImage:(UIImage *)image position:(NSNumber *)position forItem:(id<TGMediaEditableItem>)item;
- (void)setTemporaryRep:(id)rep forItem:(id<TGMediaEditableItem>)item;
- (SSignal *)fullSizeImageUrlForItem:(id<TGMediaEditableItem>)item;

View File

@ -34,6 +34,7 @@
- (void)prepareForCoverEditing;
- (void)returnFromCoverEditing;
- (NSTimeInterval)currentPosition;
- (UIImage *)screenImage;
- (UIImage *)transitionImage;
- (CGRect)editorTransitionViewRect;

View File

@ -107,6 +107,7 @@
TGMemoryImageCache *_originalThumbnailImageCache;
TGMemoryImageCache *_coverImageCache;
NSMutableDictionary *_coverPositions;
TGModernCache *_diskCache;
NSURL *_fullSizeResultsUrl;
@ -171,6 +172,7 @@
_coverImageCache = [[TGMemoryImageCache alloc] initWithSoftMemoryLimit:[[self class] thumbnailImageSoftMemoryLimit] * 10
hardMemoryLimit:[[self class] thumbnailImageHardMemoryLimit] * 10];
_coverPositions = [[NSMutableDictionary alloc] init];
NSString *diskCachePath = [[[LegacyComponentsGlobals provider] dataStoragePath] stringByAppendingPathComponent:[[self class] diskCachePath]];
_diskCache = [[TGModernCache alloc] initWithPath:diskCachePath size:[[self class] diskMemoryLimit]];
@ -945,7 +947,14 @@
return [_coverImageCache imageForKey:itemId attributes:NULL];
}
- (void)setCoverImage:(UIImage *)image forItem:(id<TGMediaEditableItem>)item
- (NSNumber *)coverPositionForItem:(NSObject<TGMediaEditableItem> *)item {
NSString *itemId = [TGMediaEditingContext _coverImageUriForItemId:item.uniqueIdentifier];
if (itemId == nil)
return nil;
return _coverPositions[itemId];
}
- (void)setCoverImage:(UIImage *)image position:(NSNumber *)position forItem:(id<TGMediaEditableItem>)item
{
NSString *itemId = [TGMediaEditingContext _coverImageUriForItemId:item.uniqueIdentifier];
if (itemId == nil)
@ -953,6 +962,7 @@
[_coverImageCache setImage:image forKey:itemId attributes:NULL];
_coverImagePipe.sink([TGMediaImageUpdate imageUpdateWithItem:item representation:image]);
[_coverPositions setObject:position forKey:itemId];
}
- (void)setFullSizeImage:(UIImage *)image forItem:(id<TGMediaEditableItem>)item

View File

@ -931,7 +931,7 @@
TGModernGalleryItemView *currentItemView = _currentItemView;
if ([currentItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]]) {
id<TGMediaEditableItem> editableMediaItem = [galleryEditableItem editableMediaItem];
[_editingContext setCoverImage:[(TGMediaPickerGalleryVideoItemView *)currentItemView screenImage] forItem:editableMediaItem];
[_editingContext setCoverImage:[(TGMediaPickerGalleryVideoItemView *)currentItemView screenImage] position:@([(TGMediaPickerGalleryVideoItemView *)currentItemView currentPosition]) forItem:editableMediaItem];
}
TGDispatchAfter(0.01, dispatch_get_main_queue(), ^{
@ -956,7 +956,7 @@
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
if (strongSelf == nil)
return;
[strongSelf->_editingContext setCoverImage:cover forItem:editableMediaItem];
[strongSelf->_editingContext setCoverImage:cover position:nil forItem:editableMediaItem];
[strongSelf coverEditorTransitionOut];
});
}

View File

@ -768,6 +768,13 @@
_isCoverEditing = true;
[self setPlayButtonHidden:true animated:true];
[self stop];
NSNumber *savedPosition = [self.item.editingContext coverPositionForItem:self.item.editableMediaItem];
if (savedPosition != nil) {
[self _seekToPosition:savedPosition.doubleValue manual:false];
[_scrubberView setValue:savedPosition.doubleValue resetPosition:true];
[_coverScrubberView setValue:savedPosition.doubleValue resetPosition:true];
}
}
- (void)returnFromCoverEditing
@ -941,6 +948,10 @@
}
}
- (NSTimeInterval)currentPosition {
return _coverScrubberView.value;
}
- (UIImage *)screenImage
{
if (_videoView != nil)

View File

@ -74,8 +74,9 @@ func telegramMediaWebpageFromApiWebpage(_ webpage: Api.WebPage) -> TelegramMedia
}
let isMediaLargeByDefault = (flags & (1 << 13)) != 0
let imageIsVideoCover = (flags & (1 << 14)) != 0
return TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.CloudWebpage, id: id), content: .Loaded(TelegramMediaWebpageLoadedContent(url: url, displayUrl: displayUrl, hash: hash, type: type, websiteName: siteName, title: title, text: description, embedUrl: embedUrl, embedType: embedType, embedSize: embedSize, duration: webpageDuration, author: author, isMediaLargeByDefault: isMediaLargeByDefault, image: image, file: file, story: story, attributes: webpageAttributes, instantPage: instantPage)))
return TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.CloudWebpage, id: id), content: .Loaded(TelegramMediaWebpageLoadedContent(url: url, displayUrl: displayUrl, hash: hash, type: type, websiteName: siteName, title: title, text: description, embedUrl: embedUrl, embedType: embedType, embedSize: embedSize, duration: webpageDuration, author: author, isMediaLargeByDefault: isMediaLargeByDefault, imageIsVideoCover: imageIsVideoCover, image: image, file: file, story: story, attributes: webpageAttributes, instantPage: instantPage)))
case .webPageEmpty:
return nil
}

View File

@ -179,6 +179,11 @@ private func findMediaResource(media: Media, previousMedia: Media?, resource: Me
if areResourcesEqual(file.resource, resource) {
return file.resource
} else {
if let videoCover = file.videoCover {
if let resource = findMediaResource(media: videoCover, previousMedia: previousMedia, resource: resource) {
return resource
}
}
for representation in file.previewRepresentations {
if areResourcesEqual(representation.resource, resource) {
return representation.resource

View File

@ -922,6 +922,10 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
public func withUpdatedAttributes(_ attributes: [TelegramMediaFileAttribute]) -> TelegramMediaFile {
return TelegramMediaFile(fileId: self.fileId, partialReference: self.partialReference, resource: self.resource, previewRepresentations: self.previewRepresentations, videoThumbnails: self.videoThumbnails, videoCover: self.videoCover, immediateThumbnailData: self.immediateThumbnailData, mimeType: self.mimeType, size: self.size, attributes: attributes, alternativeRepresentations: self.alternativeRepresentations)
}
public func withUpdatedVideoCover(_ videoCover: TelegramMediaImage?) -> TelegramMediaFile {
return TelegramMediaFile(fileId: self.fileId, partialReference: self.partialReference, resource: self.resource, previewRepresentations: self.previewRepresentations, videoThumbnails: self.videoThumbnails, videoCover: videoCover, immediateThumbnailData: self.immediateThumbnailData, mimeType: self.mimeType, size: self.size, attributes: self.attributes, alternativeRepresentations: self.alternativeRepresentations)
}
}
public func ==(lhs: TelegramMediaFile, rhs: TelegramMediaFile) -> Bool {

View File

@ -171,6 +171,7 @@ public final class TelegramMediaWebpageLoadedContent: PostboxCoding, Equatable {
public let duration: Int?
public let author: String?
public let isMediaLargeByDefault: Bool?
public let imageIsVideoCover: Bool
public let image: TelegramMediaImage?
public let file: TelegramMediaFile?
@ -192,6 +193,7 @@ public final class TelegramMediaWebpageLoadedContent: PostboxCoding, Equatable {
duration: Int?,
author: String?,
isMediaLargeByDefault: Bool?,
imageIsVideoCover: Bool,
image: TelegramMediaImage?,
file: TelegramMediaFile?,
story: TelegramMediaStory?,
@ -211,6 +213,7 @@ public final class TelegramMediaWebpageLoadedContent: PostboxCoding, Equatable {
self.duration = duration
self.author = author
self.isMediaLargeByDefault = isMediaLargeByDefault
self.imageIsVideoCover = imageIsVideoCover
self.image = image
self.file = file
self.story = story
@ -240,6 +243,7 @@ public final class TelegramMediaWebpageLoadedContent: PostboxCoding, Equatable {
}
self.author = decoder.decodeOptionalStringForKey("au")
self.isMediaLargeByDefault = decoder.decodeOptionalBoolForKey("lbd")
self.imageIsVideoCover = decoder.decodeBoolForKey("isvc", orElse: false)
if let image = decoder.decodeObjectForKey("im") as? TelegramMediaImage {
self.image = image
@ -331,6 +335,7 @@ public final class TelegramMediaWebpageLoadedContent: PostboxCoding, Equatable {
} else {
encoder.encodeNil(forKey: "lbd")
}
encoder.encodeBool(self.imageIsVideoCover, forKey: "isvc")
if let image = self.image {
encoder.encodeObject(image, forKey: "im")
} else {
@ -377,6 +382,10 @@ public func ==(lhs: TelegramMediaWebpageLoadedContent, rhs: TelegramMediaWebpage
return false
}
if lhs.imageIsVideoCover != rhs.imageIsVideoCover {
return false
}
if let lhsImage = lhs.image, let rhsImage = rhs.image {
if !lhsImage.isEqual(to: rhsImage) {
return false

View File

@ -115,6 +115,7 @@ public func webpagePreviewWithProgress(account: Account, urls: [String], webpage
duration: nil,
author: nil,
isMediaLargeByDefault: true,
imageIsVideoCover: false,
image: image,
file: nil,
story: nil,
@ -247,6 +248,7 @@ public func actualizedWebpage(account: Account, webpage: TelegramMediaWebpage) -
duration: content.duration,
author: content.author,
isMediaLargeByDefault: content.isMediaLargeByDefault,
imageIsVideoCover: content.imageIsVideoCover,
image: content.image,
file: content.file,
story: content.story,

View File

@ -1113,7 +1113,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Sent(authorName, starsPrice)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
}
case let .starGiftUnique(gift, isUpgrade, _, _, _, _, _, _, senderId, _):
case let .starGiftUnique(gift, isUpgrade, _, _, _, _, _, peerId, senderId, _):
if case let .unique(gift) = gift {
if !forAdditionalServiceMessage && !"".isEmpty {
attributedString = NSAttributedString(string: "\(gift.title) #\(gift.number)", font: titleFont, textColor: primaryTextColor)
@ -1138,10 +1138,25 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
} else if message.author?.id == accountPeerId {
attributedString = NSAttributedString(string: strings.Notification_StarsGift_TransferYou, font: titleFont, textColor: primaryTextColor)
} else if let senderId, let peer = message.peers[senderId] {
peerName = EnginePeer(peer).compactDisplayTitle
peerIds = [(0, senderId)]
let attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Transfer(peerName)._tuple, body: bodyAttributes, argumentAttributes: attributes)
if let peerId, let targetPeer = message.peers[peerId] {
if senderId == accountPeerId {
peerName = EnginePeer(targetPeer).compactDisplayTitle
peerIds = [(0, peerId)]
let attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_TransferToChannelYou(peerName)._tuple, body: bodyAttributes, argumentAttributes: attributes)
} else {
let senderPeerName = EnginePeer(targetPeer).compactDisplayTitle
peerName = EnginePeer(peer).compactDisplayTitle
peerIds = [(0, senderId), (1, peerId)]
let attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_TransferToChannel(senderPeerName, peerName)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
} else {
peerName = EnginePeer(peer).compactDisplayTitle
peerIds = [(0, senderId)]
let attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Transfer(peerName)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
} else {
let attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Transfer(peerName)._tuple, body: bodyAttributes, argumentAttributes: attributes)

View File

@ -360,7 +360,9 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
contentMediaAutomaticDownload = .prefetch
}
if file.isAnimated {
if let _ = file.videoCover {
contentMediaAutomaticPlayback = false
} else if file.isAnimated {
contentMediaAutomaticPlayback = context.sharedContext.energyUsageSettings.autoplayGif
} else if file.isVideo && context.sharedContext.energyUsageSettings.autoplayVideo {
var willDownloadOrLocal = false

View File

@ -344,7 +344,11 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
}
}
default:
if let file = mainMedia as? TelegramMediaFile, webpage.type != "telegram_theme" {
if var file = mainMedia as? TelegramMediaFile, webpage.type != "telegram_theme" {
if webpage.imageIsVideoCover, let image = webpage.image {
file = file.withUpdatedVideoCover(image)
}
if let embedUrl = webpage.embedUrl, !embedUrl.isEmpty {
if automaticPlayback {
mediaAndFlags = ([file], [.preferMediaBeforeText])
@ -689,7 +693,10 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
if let image = content.image {
mediaList.append(image)
}
if let file = content.file {
if var file = content.file {
if content.imageIsVideoCover, let image = content.image {
file = file.withUpdatedVideoCover(image)
}
mediaList.append(file)
}
updatedMedia = mediaList
@ -698,7 +705,10 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
if let image = content.image {
mediaList.append(image)
}
if let file = content.file {
if var file = content.file {
if content.imageIsVideoCover, let image = content.image {
file = file.withUpdatedVideoCover(image)
}
mediaList.append(file)
}
updatedMedia = mediaList

View File

@ -31,8 +31,13 @@ extension MediaEditorScreenImpl {
let filteredEntities = self.node.entitiesView.entities.filter { entity in
if entity is DrawingMediaEntity {
return false
} else if let entity = entity as? DrawingStickerEntity, case .message = entity.content {
return false
} else if let entity = entity as? DrawingStickerEntity {
switch entity.content {
case .message, .gift:
return false
default:
break
}
}
return true
}
@ -46,6 +51,8 @@ extension MediaEditorScreenImpl {
return false
} else if case .message = subject, !filteredValues.hasChanges && filteredEntities.isEmpty && caption.string.isEmpty {
return false
} else if case .gift = subject, !filteredValues.hasChanges && filteredEntities.isEmpty && caption.string.isEmpty {
return false
} else if case .empty = subject, !self.node.hasAnyChanges && !self.node.drawingView.internalState.canUndo {
return false
} else if case .videoCollage = subject {

View File

@ -3151,9 +3151,15 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
var effectiveSubject = subject
if case let .draft(draft, _ ) = subject {
for entity in draft.values.entities {
if case let .sticker(sticker) = entity, case let .message(ids, _, _, _, _) = sticker.content {
effectiveSubject = .message(ids)
break
if case let .sticker(sticker) = entity {
switch sticker.content {
case let .message(ids, _, _, _, _):
effectiveSubject = .message(ids)
case let .gift(gift, _):
effectiveSubject = .gift(gift)
default:
break
}
}
}
}
@ -3173,11 +3179,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
case .image, .video:
isSavingAvailable = !controller.isEmbeddedEditor
isFromCamera = true
case .draft:
isSavingAvailable = true
case .message:
isSavingAvailable = true
case .gift:
case .draft, .message,. gift:
isSavingAvailable = true
default:
isSavingAvailable = false
@ -3454,11 +3456,14 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
let renderer = DrawingMessageRenderer(context: self.context, messages: messages, parentView: self.view, isGift: isGift, wallpaperDayColor: wallpaperColors.0, wallpaperNightColor: wallpaperColors.1)
renderer.render(completion: { result in
if case .draft = subject, let existingEntityView = self.entitiesView.getView(where: { entityView in
if let stickerEntityView = entityView as? DrawingStickerEntityView, case .message = (stickerEntityView.entity as! DrawingStickerEntity).content {
return true
} else {
return false
if let stickerEntityView = entityView as? DrawingStickerEntityView {
if case .message = (stickerEntityView.entity as! DrawingStickerEntity).content {
return true
} else if case .gift = (stickerEntityView.entity as! DrawingStickerEntity).content {
return true
}
}
return false
}) as? DrawingStickerEntityView {
existingEntityView.isNightTheme = isNightTheme
let messageEntity = existingEntityView.entity as! DrawingStickerEntity
@ -6416,7 +6421,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
}
fileprivate func checkPostingAvailability() {
guard self.postingAvailabilityDisposable == nil else {
guard self.postingAvailabilityDisposable == nil && !self.isEditingStory else {
return
}
self.postingAvailabilityDisposable = (self.postingAvailabilityPromise.get()

View File

@ -10972,7 +10972,20 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
let switchToFilter: (ProfileGiftsContext.Filters) -> Void = { [weak giftsContext] value in
giftsContext?.updateFilter(value)
var updatedFilter = filter
updatedFilter.remove(.unlimited)
updatedFilter.remove(.limited)
updatedFilter.remove(.unique)
updatedFilter.insert(value)
giftsContext?.updateFilter(updatedFilter)
}
let switchToVisiblityFilter: (ProfileGiftsContext.Filters) -> Void = { [weak giftsContext] value in
var updatedFilter = filter
updatedFilter.remove(.hidden)
updatedFilter.remove(.displayed)
updatedFilter.insert(value)
giftsContext?.updateFilter(updatedFilter)
}
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unlimited, icon: { theme in
@ -11005,14 +11018,14 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}, action: { _, f in
toggleFilter(.displayed)
}, longPressAction: { _, f in
switchToFilter(.displayed)
switchToVisiblityFilter(.displayed)
})))
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Hidden, icon: { theme in
return filter.contains(.hidden) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
}, action: { _, f in
toggleFilter(.hidden)
}, longPressAction: { _, f in
switchToFilter(.hidden)
switchToVisiblityFilter(.hidden)
})))
}

View File

@ -237,7 +237,7 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode {
var media: [Media] = []
if let (site, title, text) = messageItem.linkPreview, params.width > 320.0 {
media.append(TelegramMediaWebpage(webpageId: MediaId(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: "", displayUrl: "", hash: 0, type: nil, websiteName: site, title: title, text: text, embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, image: nil, file: nil, story: nil, attributes: [], instantPage: nil))))
media.append(TelegramMediaWebpage(webpageId: MediaId(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: "", displayUrl: "", hash: 0, type: nil, websiteName: site, title: title, text: text, embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, imageIsVideoCover: false, image: nil, file: nil, story: nil, attributes: [], instantPage: nil))))
}
let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])

View File

@ -487,7 +487,6 @@ final class UserAppearanceScreenComponent: Component {
guard let self else {
return
}
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
let navigationController: NavigationController? = self.environment?.controller()?.navigationController as? NavigationController

View File

@ -586,11 +586,15 @@ public final class StoryPeerListComponent: Component {
var titleIconSize: CGSize?
if let peerStatus = component.titlePeerStatus {
let statusContent: EmojiStatusComponent.Content
var particleColor: UIColor?
switch peerStatus {
case .premium:
statusContent = .premium(color: component.theme.list.itemAccentColor)
case let .emoji(emoji):
statusContent = .animation(content: .customEmoji(fileId: emoji.fileId), size: CGSize(width: 44.0, height: 44.0), placeholderColor: component.theme.list.mediaPlaceholderColor, themeColor: component.theme.list.itemAccentColor, loopMode: .count(2))
if let color = emoji.color {
particleColor = UIColor(rgb: UInt32(bitPattern: color))
}
}
var animateStatusTransition = false
@ -618,6 +622,7 @@ public final class StoryPeerListComponent: Component {
animationCache: component.context.animationCache,
animationRenderer: component.context.animationRenderer,
content: statusContent,
particleColor: particleColor,
isVisibleForAnimations: true,
action: { [weak self] in
guard let self, let component = self.component, let titleIconView = self.titleIconView?.view else {