mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Attachment menu improvements
This commit is contained in:
@@ -7266,3 +7266,10 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Attachment.SelectFromGallery" = "Select from Gallery";
|
||||
"Attachment.SelectFromFiles" = "Select from Files";
|
||||
|
||||
"Attachment.SelectedMedia_1" = "%@ Selected";
|
||||
"Attachment.SelectedMedia_2" = "%@ Selected";
|
||||
"Attachment.SelectedMedia_3_10" = "%@ Selected";
|
||||
"Attachment.SelectedMedia_any" = "%@ Selected";
|
||||
"Attachment.SelectedMedia_many" = "%@ Selected";
|
||||
"Attachment.SelectedMedia_0" = "%@ Selected";
|
||||
|
||||
@@ -245,9 +245,9 @@ public class AttachmentController: ViewController {
|
||||
}
|
||||
|
||||
if ascending {
|
||||
strongSelf.container.container.view.layer.animatePosition(from: CGPoint(x: 70.0, y: 0.0), to: CGPoint(), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
||||
strongSelf.container.container.view.layer.animatePosition(from: CGPoint(x: 70.0, y: 0.0), to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
||||
} else {
|
||||
strongSelf.container.container.view.layer.animatePosition(from: CGPoint(x: -70.0, y: 0.0), to: CGPoint(), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
||||
strongSelf.container.container.view.layer.animatePosition(from: CGPoint(x: -70.0, y: 0.0), to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
||||
}
|
||||
|
||||
snapshotView?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||
@@ -258,7 +258,7 @@ public class AttachmentController: ViewController {
|
||||
|
||||
if let layout = strongSelf.validLayout {
|
||||
strongSelf.switchingController = true
|
||||
strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.4, curve: .spring))
|
||||
strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.3, curve: .spring))
|
||||
strongSelf.switchingController = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
#import <LegacyComponents/SGraphNode.h>
|
||||
#import <LegacyComponents/SGraphObjectNode.h>
|
||||
#import <LegacyComponents/TGActionMediaAttachment.h>
|
||||
#import <LegacyComponents/TGAlphacode.h>
|
||||
#import <LegacyComponents/TGAnimationBlockDelegate.h>
|
||||
#import <LegacyComponents/TGAttachmentCameraView.h>
|
||||
#import <LegacyComponents/TGAttachmentCarouselItemView.h>
|
||||
@@ -107,7 +106,6 @@
|
||||
#import <LegacyComponents/TGFullscreenContainerView.h>
|
||||
#import <LegacyComponents/TGGameMediaAttachment.h>
|
||||
#import <LegacyComponents/TGGifConverter.h>
|
||||
#import <LegacyComponents/TGGradientLabel.h>
|
||||
#import <LegacyComponents/TGHacks.h>
|
||||
#import <LegacyComponents/TGIconSwitchView.h>
|
||||
#import <LegacyComponents/TGImageBlur.h>
|
||||
@@ -119,16 +117,11 @@
|
||||
#import <LegacyComponents/TGImageMediaAttachment.h>
|
||||
#import <LegacyComponents/TGImageUtils.h>
|
||||
#import <LegacyComponents/TGImageView.h>
|
||||
#import <LegacyComponents/TGInputTextTag.h>
|
||||
#import <LegacyComponents/TGInstantPage.h>
|
||||
#import <LegacyComponents/TGInvoiceMediaAttachment.h>
|
||||
#import <LegacyComponents/TGItemMenuSheetPreviewView.h>
|
||||
#import <LegacyComponents/TGItemPreviewController.h>
|
||||
#import <LegacyComponents/TGItemPreviewView.h>
|
||||
#import <LegacyComponents/TGKeyCommand.h>
|
||||
#import <LegacyComponents/TGKeyCommandController.h>
|
||||
#import <LegacyComponents/TGLabel.h>
|
||||
#import <LegacyComponents/TGLetteredAvatarView.h>
|
||||
#import <LegacyComponents/TGListsTableView.h>
|
||||
#import <LegacyComponents/TGLiveUploadInterface.h>
|
||||
#import <LegacyComponents/TGLocalMessageMetaMediaAttachment.h>
|
||||
@@ -249,7 +242,6 @@
|
||||
#import <LegacyComponents/TGProgressWindow.h>
|
||||
#import <LegacyComponents/TGProxyWindow.h>
|
||||
#import <LegacyComponents/TGRTLScreenEdgePanGestureRecognizer.h>
|
||||
#import <LegacyComponents/TGRemoteImageView.h>
|
||||
#import <LegacyComponents/TGReplyMarkupAttachment.h>
|
||||
#import <LegacyComponents/TGReplyMessageMediaAttachment.h>
|
||||
#import <LegacyComponents/TGStaticBackdropAreaData.h>
|
||||
@@ -258,13 +250,11 @@
|
||||
#import <LegacyComponents/TGStickerPack.h>
|
||||
#import <LegacyComponents/TGStickerPackReference.h>
|
||||
#import <LegacyComponents/TGStringUtils.h>
|
||||
#import <LegacyComponents/TGSuggestionContext.h>
|
||||
#import <LegacyComponents/TGTextCheckingResult.h>
|
||||
#import <LegacyComponents/TGTimerTarget.h>
|
||||
#import <LegacyComponents/TGToolbarButton.h>
|
||||
#import <LegacyComponents/TGTooltipView.h>
|
||||
#import <LegacyComponents/TGUnsupportedMediaAttachment.h>
|
||||
#import <LegacyComponents/TGUser.h>
|
||||
#import <LegacyComponents/TGViaUserAttachment.h>
|
||||
#import <LegacyComponents/TGVideoEditAdjustments.h>
|
||||
#import <LegacyComponents/TGVideoInfo.h>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class SSignal;
|
||||
|
||||
@interface TGAlphacodeEntry : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString *emoji;
|
||||
@property (nonatomic, strong, readonly) NSString *code;
|
||||
|
||||
- (instancetype)initWithEmoji:(NSString *)emoji code:(NSString *)code;
|
||||
|
||||
@end
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
@class TGMediaSelectionContext;
|
||||
@class TGMediaEditingContext;
|
||||
@class TGSuggestionContext;
|
||||
@class TGViewController;
|
||||
@class TGAttachmentCameraView;
|
||||
@class TGVideoEditAdjustments;
|
||||
@@ -22,7 +21,6 @@
|
||||
|
||||
@property (nonatomic, readonly) TGMediaSelectionContext *selectionContext;
|
||||
@property (nonatomic, readonly) TGMediaEditingContext *editingContext;
|
||||
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
|
||||
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
||||
@property (nonatomic) bool allowCaptions;
|
||||
@property (nonatomic) bool allowCaptionEntities;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
@class TGCameraPreviewView;
|
||||
@class TGMediaSelectionContext;
|
||||
@class TGMediaEditingContext;
|
||||
@class TGSuggestionContext;
|
||||
@class TGVideoEditAdjustments;
|
||||
|
||||
@protocol TGPhotoPaintStickersContext;
|
||||
@@ -42,7 +41,6 @@ typedef enum {
|
||||
@property (nonatomic, assign) bool hasSilentPosting;
|
||||
@property (nonatomic, assign) bool hasSchedule;
|
||||
@property (nonatomic, assign) bool reminder;
|
||||
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
|
||||
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
||||
@property (nonatomic, assign) bool shortcut;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
@property (nonatomic, copy) void (^presentScheduleController)(void (^)(int32_t));
|
||||
@property (nonatomic, copy) void (^presentTimerController)(void (^)(int32_t));
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context image:(UIImage *)image images:(NSArray *)images parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder recipientName:(NSString *)recipientName;
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context image:(UIImage *)image images:(NSArray *)images parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder recipientName:(NSString *)recipientName;
|
||||
|
||||
- (void)present;
|
||||
|
||||
|
||||
@@ -7,14 +7,13 @@
|
||||
|
||||
@class TGMediaSelectionContext;
|
||||
@class TGMediaEditingContext;
|
||||
@class TGSuggestionContext;
|
||||
|
||||
@protocol TGMediaSelectableItem;
|
||||
@protocol TGPhotoPaintStickersContext;
|
||||
|
||||
@interface TGClipboardMenu : NSObject
|
||||
|
||||
+ (TGMenuSheetController *)presentInParentController:(TGViewController *)parentController context:(id<LegacyComponentsContext>)context images:(NSArray *)images allowGrouping:(bool)allowGrouping hasCaption:(bool)hasCaption hasTimer:(bool)hasTimer hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder recipientName:(NSString *)recipientName suggestionContext:(TGSuggestionContext *)suggestionContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext presentScheduleController:(void (^)(void(^)(int32_t)))presentScheduleController presentTimerController:(void (^)(void(^)(int32_t)))presentTimerController completed:(void (^)(TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id<TGMediaSelectableItem> currentItem, bool silentPosting, int32_t scheduleTime))completed dismissed:(void (^)(void))dismissed sourceView:(UIView *)sourceView sourceRect:(CGRect (^)(void))sourceRect;
|
||||
+ (TGMenuSheetController *)presentInParentController:(TGViewController *)parentController context:(id<LegacyComponentsContext>)context images:(NSArray *)images allowGrouping:(bool)allowGrouping hasCaption:(bool)hasCaption hasTimer:(bool)hasTimer hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder recipientName:(NSString *)recipientName stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext presentScheduleController:(void (^)(void(^)(int32_t)))presentScheduleController presentTimerController:(void (^)(void(^)(int32_t)))presentTimerController completed:(void (^)(TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id<TGMediaSelectableItem> currentItem, bool silentPosting, int32_t scheduleTime))completed dismissed:(void (^)(void))dismissed sourceView:(UIView *)sourceView sourceRect:(CGRect (^)(void))sourceRect;
|
||||
|
||||
+ (NSArray *)resultSignalsForSelectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext currentItem:(id<TGMediaSelectableItem>)currentItem descriptionGenerator:(id (^)(id, NSAttributedString *,
|
||||
NSString *))descriptionGenerator;
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
+ (NSString *)stringForPreciseDate:(int)date;
|
||||
+ (NSString *)stringForMessageListDate:(int)date;
|
||||
+ (NSString *)stringForApproximateDate:(int)date;
|
||||
+ (NSString *)stringForRelativeLastSeen:(int)date;
|
||||
+ (NSString *)stringForRelativeUpdate:(int)date;
|
||||
+ (NSString *)stringForFullDate:(int)date;
|
||||
+ (NSString *)stringForCallsListDate:(int)date;
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface TGGradientLabel : UIView
|
||||
|
||||
@property (nonatomic, strong) UIFont *font;
|
||||
@property (nonatomic, strong) NSString *text;
|
||||
@property (nonatomic) int topColor;
|
||||
@property (nonatomic) int bottomColor;
|
||||
@property (nonatomic) UIColor *textColor;
|
||||
|
||||
@end
|
||||
@@ -1,21 +0,0 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface TGInputTextTag : NSTextAttachment
|
||||
|
||||
@property (nonatomic, readonly) int64_t uniqueId;
|
||||
@property (nonatomic, readonly) bool left;
|
||||
@property (nonatomic, strong, readonly) id attachment;
|
||||
|
||||
- (instancetype)initWithUniqueId:(int64_t)uniqueId left:(bool)left attachment:(id)attachment;
|
||||
|
||||
@end
|
||||
|
||||
@interface TGInputTextTagAndRange : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) TGInputTextTag *tag;
|
||||
@property (nonatomic) NSRange range;
|
||||
|
||||
- (instancetype)initWithTag:(TGInputTextTag *)tag range:(NSRange)range;
|
||||
|
||||
@end
|
||||
@@ -1,25 +0,0 @@
|
||||
#import "TGItemPreviewView.h"
|
||||
|
||||
#import <LegacyComponents/LegacyComponentsContext.h>
|
||||
|
||||
@interface TGItemMenuSheetPreviewView : TGItemPreviewView
|
||||
{
|
||||
UIView *_containerView;
|
||||
}
|
||||
|
||||
@property (nonatomic, assign) bool presentActionsImmediately;
|
||||
@property (nonatomic, assign) bool dontBlurOnPresentation;
|
||||
@property (nonatomic, readonly) bool actionsPresented;
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context frame:(CGRect)frame;
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context mainItemViews:(NSArray *)mainItemViews actionItemViews:(NSArray *)actionItemViews;
|
||||
- (void)setupWithMainItemViews:(NSArray *)mainItemViews actionItemViews:(NSArray *)actionItemViews;
|
||||
|
||||
- (void)setActionItemViews:(NSArray *)actionsView animated:(bool)animated;
|
||||
|
||||
- (void)performCommit;
|
||||
- (void)performDismissal;
|
||||
|
||||
- (void)presentActions:(void (^)(void))animationBlock;
|
||||
|
||||
@end
|
||||
@@ -1,19 +0,0 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <LegacyComponents/LegacyComponentsContext.h>
|
||||
#import <LegacyComponents/TGOverlayController.h>
|
||||
|
||||
@class TGItemPreviewView;
|
||||
|
||||
@interface TGItemPreviewController : TGOverlayController
|
||||
|
||||
@property (nonatomic, copy) void (^onDismiss)(void);
|
||||
|
||||
@property (nonatomic, copy) CGPoint (^sourcePointForItem)(id item);
|
||||
@property (nonatomic, readonly) TGItemPreviewView *previewView;
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController previewView:(TGItemPreviewView *)previewView;
|
||||
- (void)dismiss;
|
||||
- (void)dismissImmediately;
|
||||
|
||||
@end
|
||||
@@ -1,31 +0,0 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface TGItemPreviewView : UIView
|
||||
|
||||
@property (nonatomic, readonly) UIView *dimView;
|
||||
@property (nonatomic, readonly) UIView *wrapperView;
|
||||
|
||||
@property (nonatomic, copy) CGPoint (^sourcePointForItem)(id item);
|
||||
@property (nonatomic, copy) void (^onDismiss)(void);
|
||||
@property (nonatomic, copy) void (^willDismiss)(void);
|
||||
|
||||
@property (nonatomic, assign) bool eccentric;
|
||||
@property (nonatomic, strong) id item;
|
||||
@property (nonatomic, assign) bool isLocked;
|
||||
|
||||
@property (nonatomic, assign) UIEdgeInsets safeAreaInset;
|
||||
|
||||
- (void)animateAppear;
|
||||
- (void)animateDismiss:(void (^)())completion;
|
||||
|
||||
- (void)_handlePanOffset:(CGFloat)offset;
|
||||
- (void)_handlePressEnded;
|
||||
|
||||
- (bool)_maybeLockWithVelocity:(CGFloat)velocity;
|
||||
|
||||
- (CGPoint)_wrapperViewContainerCenter;
|
||||
|
||||
- (void)_didAppear;
|
||||
- (void)_willDisappear;
|
||||
|
||||
@end
|
||||
@@ -1,16 +0,0 @@
|
||||
#import "TGRemoteImageView.h"
|
||||
|
||||
@interface TGLetteredAvatarView : TGRemoteImageView
|
||||
|
||||
- (void)setSingleFontSize:(CGFloat)singleFontSize doubleFontSize:(CGFloat)doubleFontSize useBoldFont:(bool)useBoldFont;
|
||||
|
||||
- (void)setFirstName:(NSString *)firstName lastName:(NSString *)lastName;
|
||||
- (void)setTitle:(NSString *)title;
|
||||
|
||||
- (void)setTitleNeedsDisplay;
|
||||
|
||||
- (void)loadUserPlaceholderWithSize:(CGSize)size uid:(int64_t)uid firstName:(NSString *)firstName lastName:(NSString *)lastName placeholder:(UIImage *)placeholder;
|
||||
- (void)loadGroupPlaceholderWithSize:(CGSize)size conversationId:(int64_t)conversationId title:(NSString *)title placeholder:(UIImage *)placeholder;
|
||||
- (void)loadSavedMessagesWithSize:(CGSize)size placeholder:(UIImage *)placeholder;
|
||||
|
||||
@end
|
||||
@@ -2,7 +2,6 @@
|
||||
#import <LegacyComponents/LegacyComponentsContext.h>
|
||||
|
||||
#import <LegacyComponents/TGMediaAssetsLibrary.h>
|
||||
#import <LegacyComponents/TGSuggestionContext.h>
|
||||
|
||||
#import <LegacyComponents/TGMediaAssetsUtils.h>
|
||||
|
||||
@@ -53,7 +52,6 @@ typedef enum
|
||||
|
||||
@property (nonatomic, readonly) TGMediaEditingContext *editingContext;
|
||||
@property (nonatomic, readonly) TGMediaSelectionContext *selectionContext;
|
||||
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
|
||||
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
||||
@property (nonatomic, assign) bool localMediaCacheEnabled;
|
||||
@property (nonatomic, assign) bool captionsEnabled;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#import <LegacyComponents/TGViewController.h>
|
||||
|
||||
#import <LegacyComponents/TGSuggestionContext.h>
|
||||
|
||||
@class TGMediaPickerLayoutMetrics;
|
||||
@class TGMediaSelectionContext;
|
||||
@class TGMediaEditingContext;
|
||||
@@ -19,7 +17,6 @@
|
||||
TGMediaPickerSelectionGestureRecognizer *_selectionGestureRecognizer;
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
|
||||
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
||||
@property (nonatomic, assign) bool localMediaCacheEnabled;
|
||||
@property (nonatomic, assign) bool captionsEnabled;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
@protocol TGPhotoPaintStickersContext;
|
||||
@class TGMediaSelectionContext;
|
||||
@class TGMediaEditingContext;
|
||||
@class TGSuggestionContext;
|
||||
@class TGMediaPickerGallerySelectedItemsModel;
|
||||
|
||||
@interface TGMediaPickerGalleryInterfaceView : UIView <TGModernGalleryInterfaceView>
|
||||
@@ -42,7 +41,6 @@
|
||||
|
||||
- (void)setSelectedItemsModel:(TGMediaPickerGallerySelectedItemsModel *)selectedItemsModel;
|
||||
- (void)setEditorTabPressed:(void (^)(TGPhotoEditorTab tab))editorTabPressed;
|
||||
- (void)setSuggestionContext:(TGSuggestionContext *)suggestionContext;
|
||||
|
||||
- (void)setThumbnailSignalForItem:(SSignal *(^)(id))thumbnailSignalForItem;
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
|
||||
@protocol TGPhotoPaintStickersContext;
|
||||
|
||||
@class TGSuggestionContext;
|
||||
|
||||
@interface TGMediaPickerGalleryModel : TGModernGalleryModel
|
||||
|
||||
@property (nonatomic, copy) void (^willFinishEditingItem)(id<TGMediaEditableItem> item, id<TGMediaEditAdjustments> adjustments, id temporaryRep, bool hasChanges);
|
||||
@@ -45,7 +43,6 @@
|
||||
@property (nonatomic, copy) NSInteger (^externalSelectionCount)(void);
|
||||
|
||||
@property (nonatomic, readonly) TGMediaSelectionContext *selectionContext;
|
||||
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
|
||||
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context items:(NSArray *)items focusItem:(id<TGModernGalleryItem>)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions hasSelectionPanel:(bool)hasSelectionPanel hasCamera:(bool)hasCamera recipientName:(NSString *)recipientName;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#import <LegacyComponents/TGModernGalleryEditableItem.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
@class TGMediaAssetFetchResult;
|
||||
@protocol TGMediaEditAdjustments;
|
||||
|
||||
@interface TGMediaPickerGalleryVideoItem : TGMediaPickerGalleryItem <TGModernGallerySelectableItem, TGModernGalleryEditableItem>
|
||||
@@ -12,3 +13,13 @@
|
||||
- (SSignal *)durationSignal;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@interface TGMediaPickerGalleryFetchResultItem : TGMediaPickerGalleryItem <TGModernGallerySelectableItem, TGModernGalleryEditableItem>
|
||||
|
||||
@property (nonatomic, readonly) TGMediaPickerGalleryItem<TGModernGallerySelectableItem, TGModernGalleryEditableItem> *backingItem;
|
||||
|
||||
- (instancetype)initWithFetchResult:(TGMediaAssetFetchResult *)fetchResult index:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
@class TGMediaSelectionContext;
|
||||
@class TGMediaEditingContext;
|
||||
@class TGSuggestionContext;
|
||||
@class TGMediaPickerGalleryItem;
|
||||
@class TGMediaAssetFetchResult;
|
||||
@class TGMediaAssetMomentList;
|
||||
@@ -32,9 +31,9 @@
|
||||
@property (nonatomic, copy) void (^presentScheduleController)(void (^)(int32_t));
|
||||
@property (nonatomic, copy) void (^presentTimerController)(void (^)(int32_t));
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext;
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext;
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext;
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext;
|
||||
|
||||
- (void)present;
|
||||
- (void)updateWithFetchResult:(TGMediaAssetFetchResult *)fetchResult;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class TGSuggestionContext;
|
||||
@protocol TGPhotoPaintStickersContext;
|
||||
@protocol TGCaptionPanelView;
|
||||
|
||||
@@ -18,8 +17,6 @@
|
||||
@property (nonatomic, assign) CGFloat contentAreaHeight;
|
||||
@property (nonatomic, assign) bool allowEntities;
|
||||
|
||||
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
|
||||
|
||||
@property (nonatomic, copy) UIView *(^panelParentView)(void);
|
||||
|
||||
@property (nonatomic, copy) void (^panelFocused)(void);
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
@class SSignal;
|
||||
@class PGCameraShotMetadata;
|
||||
@class TGSuggestionContext;
|
||||
@class TGPhotoEditorController;
|
||||
@class AVPlayer;
|
||||
|
||||
@@ -26,7 +25,6 @@ typedef enum {
|
||||
|
||||
@interface TGPhotoEditorController : TGOverlayController
|
||||
|
||||
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
|
||||
@property (nonatomic, strong) TGMediaEditingContext *editingContext;
|
||||
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
||||
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <LegacyComponents/ActionStage.h>
|
||||
#import <LegacyComponents/TGCache.h>
|
||||
|
||||
#define TG_CACHE_INPLACE false
|
||||
|
||||
typedef enum {
|
||||
TGRemoteImageContentHintLargeFile = 1,
|
||||
TGRemoteImageContentHintSaveToGallery = 2,
|
||||
TGRemoteImageContentHintLoadFromDiskSynchronously = 4,
|
||||
TGRemoteImageContentHintBlurRemote = 8
|
||||
} TGRemoteImageContentHints;
|
||||
|
||||
@class TGRemoteImageView;
|
||||
|
||||
typedef UIImage *(^TGImageProcessor)(UIImage *);
|
||||
typedef UIImage *(^TGImageUniversalProcessor)(NSString *, UIImage *);
|
||||
|
||||
typedef void (^TGImageProgressHandler)(TGRemoteImageView *imageView, float progress);
|
||||
|
||||
@interface TGRemoteImageView : UIImageView
|
||||
<ASWatcher>
|
||||
@property (nonatomic, strong) ASHandle *actionHandle;
|
||||
@property (nonatomic, strong) NSString *reuseIdentifier;
|
||||
|
||||
@property (nonatomic, strong) TGCache *cache;
|
||||
@property (nonatomic) bool useCache;
|
||||
@property (nonatomic) int contentHints;
|
||||
@property (nonatomic) id userProperties;
|
||||
|
||||
@property (nonatomic) bool fadeTransition;
|
||||
@property (nonatomic) NSTimeInterval fadeTransitionDuration;
|
||||
@property (nonatomic) bool allowThumbnailCache;
|
||||
|
||||
#if TGRemoteImageUseContents
|
||||
@property (nonatomic, strong) UIImage *image;
|
||||
#endif
|
||||
@property (nonatomic, strong) UIView *placeholderOverlay;
|
||||
|
||||
@property (nonatomic, strong) NSString *currentUrl;
|
||||
@property (nonatomic, strong) NSString *currentFilter;
|
||||
|
||||
@property (nonatomic, copy) TGImageProgressHandler progressHandler;
|
||||
|
||||
@property (nonatomic) int cancelTimeout;
|
||||
|
||||
+ (void)throttleDownProcessing;
|
||||
+ (void)registerImageUniversalProcessor:(TGImageUniversalProcessor)universalProcessor withBaseName:(NSString *)baseName;
|
||||
+ (void)registerImageProcessor:(TGImageProcessor)imageProcessor withName:(NSString *)name;
|
||||
+ (TGImageProcessor)imageProcessorForName:(NSString *)name;
|
||||
|
||||
+ (void)setSharedCache:(TGCache *)cache;
|
||||
+ (TGCache *)sharedCache;
|
||||
|
||||
- (UIImage *)currentImage;
|
||||
- (UIImage *)currentPlaceholderImage;
|
||||
|
||||
- (void)tryFillCache:(NSMutableDictionary *)dict;
|
||||
|
||||
- (void)loadImage:(UIImage *)image;
|
||||
- (void)loadImage:(NSString *)url filter:(NSString *)filter placeholder:(UIImage *)placeholder;
|
||||
- (void)loadImage:(NSString *)url filter:(NSString *)filter placeholder:(UIImage *)placeholder forceFade:(bool)forceFade;
|
||||
- (void)loadPlaceholder:(UIImage *)placeholder;
|
||||
- (void)cancelLoading;
|
||||
|
||||
+ (UIImage *)imageFromCache:(NSString *)url filter:(NSString *)filter cache:(TGCache *)cache;
|
||||
+ (NSString *)preloadImage:(NSString *)url filter:(NSString *)filter blurIfRemote:(bool)blurIfRemote cache:(TGCache *)cache allowThumbnailCache:(bool)allowThumbnailCache watcher:(id<ASWatcher>)watcher;
|
||||
|
||||
- (void)prepareForRecycle;
|
||||
- (void)prepareForReuse;
|
||||
|
||||
@end
|
||||
@@ -1,11 +0,0 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class SSignal;
|
||||
|
||||
@interface TGSuggestionContext : NSObject
|
||||
|
||||
@property (nonatomic, copy) SSignal *(^userListSignal)(NSString *mention);
|
||||
@property (nonatomic, copy) SSignal *(^hashtagListSignal)(NSString *hashtag);
|
||||
@property (nonatomic, copy) SSignal *(^alphacodeSignal)(NSString *alphacode, NSString *languageCode);
|
||||
|
||||
@end
|
||||
@@ -1,133 +0,0 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <LegacyComponents/PSCoding.h>
|
||||
#import <LegacyComponents/TGBotInfo.h>
|
||||
|
||||
typedef enum {
|
||||
TGUserSexUnknown = 0,
|
||||
TGUserSexMale = 1,
|
||||
TGUserSexFemale = 2
|
||||
} TGUserSex;
|
||||
|
||||
typedef enum {
|
||||
TGUserPresenceValueLately = -2,
|
||||
TGUserPresenceValueWithinAWeek = -3,
|
||||
TGUserPresenceValueWithinAMonth = -4,
|
||||
TGUserPresenceValueALongTimeAgo = -5
|
||||
} TGUserPresenceValue;
|
||||
|
||||
typedef struct {
|
||||
bool online;
|
||||
int lastSeen;
|
||||
int temporaryLastSeen;
|
||||
} TGUserPresence;
|
||||
|
||||
typedef enum {
|
||||
TGUserLinkKnown = 1,
|
||||
TGUserLinkForeignRequested = 2,
|
||||
TGUserLinkForeignMutual = 4,
|
||||
TGUserLinkMyRequested = 8,
|
||||
TGUserLinkMyContact = 16,
|
||||
TGUserLinkForeignHasPhone = 32
|
||||
} TGUserLink;
|
||||
|
||||
typedef enum {
|
||||
TGUserFieldUid = 1,
|
||||
TGUserFieldPhoneNumber = 2,
|
||||
TGUserFieldPhoneNumberHash = 4,
|
||||
TGUserFieldFirstName = 8,
|
||||
TGUserFieldLastName = 16,
|
||||
TGUserFieldPhonebookFirstName = 32,
|
||||
TGUserFieldPhonebookLastName = 64,
|
||||
TGUserFieldSex = 128,
|
||||
TGUserFieldPhotoUrlSmall = 256,
|
||||
TGUserFieldPhotoUrlMedium = 512,
|
||||
TGUserFieldPhotoUrlBig = 1024,
|
||||
TGUserFieldPresenceLastSeen = 2048,
|
||||
TGUserFieldPresenceOnline = 4096,
|
||||
TGUserFieldUsername = 8192,
|
||||
TGUserFieldOther = 8192 * 2
|
||||
} TGUserFields;
|
||||
|
||||
typedef enum {
|
||||
TGUserKindGeneric = 0,
|
||||
TGUserKindBot = 1,
|
||||
TGUserKindSmartBot = 2
|
||||
} TGUserKind;
|
||||
|
||||
typedef enum {
|
||||
TGBotKindGeneric = 0,
|
||||
TGBotKindPrivate = 1
|
||||
} TGBotKind;
|
||||
|
||||
@class TGNotificationPrivacyAccountSetting;
|
||||
|
||||
#define TGUserFieldsAllButPresenceMask (TGUserFieldUid | TGUserFieldPhoneNumber | TGUserFieldPhoneNumberHash | TGUserFieldFirstName| TGUserFieldLastName | TGUserFieldPhonebookFirstName | TGUserFieldPhonebookLastName | TGUserFieldSex | TGUserFieldPhotoUrlSmall | TGUserFieldPhotoUrlMedium | TGUserFieldPhotoUrlBig)
|
||||
|
||||
@interface TGUser : NSObject <PSCoding>
|
||||
|
||||
@property (nonatomic) int64_t uid;
|
||||
@property (nonatomic, strong) NSString *phoneNumber;
|
||||
@property (nonatomic) int64_t phoneNumberHash;
|
||||
@property (nonatomic, strong) NSString *firstName;
|
||||
@property (nonatomic, strong) NSString *lastName;
|
||||
@property (nonatomic, strong) NSString *userName;
|
||||
@property (nonatomic, strong) NSString *phonebookFirstName;
|
||||
@property (nonatomic, strong) NSString *phonebookLastName;
|
||||
@property (nonatomic) TGUserSex sex;
|
||||
@property (nonatomic) NSString *photoUrlSmall;
|
||||
@property (nonatomic) NSString *photoUrlMedium;
|
||||
@property (nonatomic) NSString *photoUrlBig;
|
||||
@property (nonatomic) NSData *photoFileReferenceSmall;
|
||||
@property (nonatomic) NSData *photoFileReferenceBig;
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString *photoFullUrlSmall;
|
||||
@property (nonatomic, strong, readonly) NSString *photoFullUrlBig;
|
||||
|
||||
@property (nonatomic) TGUserPresence presence;
|
||||
|
||||
@property (nonatomic) int contactId;
|
||||
|
||||
@property (nonatomic) int32_t kind;
|
||||
@property (nonatomic) int32_t botKind;
|
||||
@property (nonatomic) int32_t botInfoVersion;
|
||||
|
||||
@property (nonatomic) int32_t flags;
|
||||
|
||||
@property (nonatomic) bool isVerified;
|
||||
@property (nonatomic) bool hasExplicitContent;
|
||||
@property (nonatomic, strong) NSString *restrictionReason;
|
||||
@property (nonatomic, strong) NSString *contextBotPlaceholder;
|
||||
@property (nonatomic) bool isContextBot;
|
||||
|
||||
@property (nonatomic, strong) NSDictionary *customProperties;
|
||||
|
||||
@property (nonatomic) bool minimalRepresentation;
|
||||
|
||||
@property (nonatomic, strong) NSString *about;
|
||||
|
||||
@property (nonatomic) bool botInlineGeo;
|
||||
|
||||
@property (nonatomic, readonly) bool isBot;
|
||||
@property (nonatomic, readonly) bool isDeleted;
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone;
|
||||
|
||||
- (bool)hasAnyName;
|
||||
|
||||
- (NSString *)realFirstName;
|
||||
- (NSString *)realLastName;
|
||||
|
||||
- (NSString *)displayName;
|
||||
- (NSString *)displayRealName;
|
||||
- (NSString *)displayFirstName;
|
||||
- (NSString *)compactName;
|
||||
|
||||
- (NSString *)formattedPhoneNumber;
|
||||
|
||||
- (bool)isEqualToUser:(TGUser *)anotherUser;
|
||||
- (int)differenceFromUser:(TGUser *)anotherUser;
|
||||
|
||||
+ (TGUserPresence)approximatePresenceFromPresence:(TGUserPresence)presence currentTime:(NSTimeInterval)currentTime;
|
||||
|
||||
@end
|
||||
@@ -1,14 +0,0 @@
|
||||
#import "TGAlphacode.h"
|
||||
|
||||
@implementation TGAlphacodeEntry
|
||||
|
||||
- (instancetype)initWithEmoji:(NSString *)emoji code:(NSString *)code {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_emoji = emoji;
|
||||
_code = code;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -839,7 +839,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
if ([cell isKindOfClass:[TGAttachmentAssetCell class]])
|
||||
thumbnailImage = cell.imageView.image;
|
||||
|
||||
TGMediaPickerModernGalleryMixin *mixin = [[TGMediaPickerModernGalleryMixin alloc] initWithContext:_context item:asset fetchResult:_fetchResult parentController:self.parentController thumbnailImage:thumbnailImage selectionContext:_selectionContext editingContext:_editingContext suggestionContext:self.suggestionContext hasCaptions:(_allowCaptions && !_forProfilePhoto) allowCaptionEntities:self.allowCaptionEntities hasTimer:self.hasTimer onlyCrop:self.onlyCrop inhibitDocumentCaptions:_inhibitDocumentCaptions inhibitMute:self.inhibitMute asFile:self.asFile itemsLimit:TGAttachmentDisplayedAssetLimit recipientName:self.recipientName hasSilentPosting:self.hasSilentPosting hasSchedule:self.hasSchedule reminder:self.reminder stickersContext:self.stickersContext];
|
||||
TGMediaPickerModernGalleryMixin *mixin = [[TGMediaPickerModernGalleryMixin alloc] initWithContext:_context item:asset fetchResult:_fetchResult parentController:self.parentController thumbnailImage:thumbnailImage selectionContext:_selectionContext editingContext:_editingContext hasCaptions:(_allowCaptions && !_forProfilePhoto) allowCaptionEntities:self.allowCaptionEntities hasTimer:self.hasTimer onlyCrop:self.onlyCrop inhibitDocumentCaptions:_inhibitDocumentCaptions inhibitMute:self.inhibitMute asFile:self.asFile itemsLimit:TGAttachmentDisplayedAssetLimit recipientName:self.recipientName hasSilentPosting:self.hasSilentPosting hasSchedule:self.hasSchedule reminder:self.reminder stickersContext:self.stickersContext];
|
||||
mixin.presentScheduleController = self.presentScheduleController;
|
||||
mixin.presentTimerController = self.presentTimerController;
|
||||
__weak TGAttachmentCarouselItemView *weakSelf = self;
|
||||
|
||||
@@ -1531,7 +1531,6 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
TGMediaPickerGalleryModel *model = [[TGMediaPickerGalleryModel alloc] initWithContext:windowContext items:galleryItems focusItem:focusItem selectionContext:_items.count > 1 ? selectionContext : nil editingContext:editingContext hasCaptions:self.allowCaptions allowCaptionEntities:self.allowCaptionEntities hasTimer:self.hasTimer onlyCrop:_intent == TGCameraControllerPassportIntent || _intent == TGCameraControllerPassportIdIntent || _intent == TGCameraControllerPassportMultipleIntent inhibitDocumentCaptions:self.inhibitDocumentCaptions hasSelectionPanel:true hasCamera:hasCamera recipientName:self.recipientName];
|
||||
model.inhibitMute = self.inhibitMute;
|
||||
model.controller = galleryController;
|
||||
model.suggestionContext = self.suggestionContext;
|
||||
model.stickersContext = self.stickersContext;
|
||||
|
||||
__weak TGModernGalleryController *weakGalleryController = galleryController;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#import <LegacyComponents/TGMediaEditingContext.h>
|
||||
#import <LegacyComponents/TGMediaSelectionContext.h>
|
||||
#import <LegacyComponents/TGSuggestionContext.h>
|
||||
|
||||
#import <LegacyComponents/TGMediaAsset.h>
|
||||
#import <LegacyComponents/TGMediaAssetFetchResult.h>
|
||||
@@ -39,7 +38,7 @@
|
||||
|
||||
@implementation TGClipboardGalleryMixin
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context image:(UIImage *)image images:(NSArray *)images parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder recipientName:(NSString *)recipientName
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context image:(UIImage *)image images:(NSArray *)images parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder recipientName:(NSString *)recipientName
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
@@ -68,7 +67,6 @@
|
||||
TGClipboardGalleryModel *model = [[TGClipboardGalleryModel alloc] initWithContext:_context images:images focusIndex:focusIndex selectionContext:selectionContext editingContext:editingContext stickersContext:stickersContext hasCaptions:hasCaptions hasTimer:hasTimer hasSelectionPanel:false recipientName:recipientName];
|
||||
_galleryModel = model;
|
||||
model.controller = modernGallery;
|
||||
model.suggestionContext = suggestionContext;
|
||||
model.willFinishEditingItem = ^(id<TGMediaEditableItem> editableItem, id<TGMediaEditAdjustments> adjustments, id representation, bool hasChanges)
|
||||
{
|
||||
__strong TGClipboardGalleryMixin *strongSelf = weakSelf;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
@property (nonatomic, readonly, strong) TGMediaPickerGallerySelectedItemsModel *selectedItemsModel;
|
||||
|
||||
@property (nonatomic, readonly) TGMediaSelectionContext *selectionContext;
|
||||
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
|
||||
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context images:(NSArray *)images focusIndex:(NSUInteger)focusIndex selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer hasSelectionPanel:(bool)hasSelectionPanel recipientName:(NSString *)recipientName;
|
||||
|
||||
@@ -171,12 +171,6 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setSuggestionContext:(TGSuggestionContext *)suggestionContext
|
||||
{
|
||||
_suggestionContext = suggestionContext;
|
||||
[_interfaceView setSuggestionContext:suggestionContext];
|
||||
}
|
||||
|
||||
- (NSInteger)selectionCount
|
||||
{
|
||||
return _selectedItemsModel.selectedCount;
|
||||
@@ -326,7 +320,6 @@
|
||||
controller.editingContext = _editingContext;
|
||||
controller.stickersContext = _stickersContext;
|
||||
self.editorController = controller;
|
||||
controller.suggestionContext = self.suggestionContext;
|
||||
controller.willFinishEditing = ^(id<TGMediaEditAdjustments> adjustments, id temporaryRep, bool hasChanges)
|
||||
{
|
||||
__strong TGClipboardGalleryModel *strongSelf = weakSelf;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
@implementation TGClipboardMenu
|
||||
|
||||
+ (TGMenuSheetController *)presentInParentController:(TGViewController *)parentController context:(id<LegacyComponentsContext>)context images:(NSArray *)images allowGrouping:(bool)allowGrouping hasCaption:(bool)hasCaption hasTimer:(bool)hasTimer hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder recipientName:(NSString *)recipientName suggestionContext:(TGSuggestionContext *)suggestionContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext presentScheduleController:(void (^)(void(^)(int32_t)))presentScheduleController presentTimerController:(void (^)(void(^)(int32_t)))presentTimerController completed:(void (^)(TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id<TGMediaSelectableItem> currentItem, bool silentPosting, int32_t scheduleTime))completed dismissed:(void (^)(void))dismissed sourceView:(UIView *)sourceView sourceRect:(CGRect (^)(void))sourceRect
|
||||
+ (TGMenuSheetController *)presentInParentController:(TGViewController *)parentController context:(id<LegacyComponentsContext>)context images:(NSArray *)images allowGrouping:(bool)allowGrouping hasCaption:(bool)hasCaption hasTimer:(bool)hasTimer hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder recipientName:(NSString *)recipientName stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext presentScheduleController:(void (^)(void(^)(int32_t)))presentScheduleController presentTimerController:(void (^)(void(^)(int32_t)))presentTimerController completed:(void (^)(TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id<TGMediaSelectableItem> currentItem, bool silentPosting, int32_t scheduleTime))completed dismissed:(void (^)(void))dismissed sourceView:(UIView *)sourceView sourceRect:(CGRect (^)(void))sourceRect
|
||||
{
|
||||
bool centered = false;
|
||||
if (sourceRect == nil)
|
||||
@@ -42,7 +42,6 @@
|
||||
TGClipboardPreviewItemView *previewItem = [[TGClipboardPreviewItemView alloc] initWithContext:context images:images allowGrouping:allowGrouping];
|
||||
__weak TGClipboardPreviewItemView *weakPreviewItem = previewItem;
|
||||
previewItem.stickersContext = stickersContext;
|
||||
previewItem.suggestionContext = suggestionContext;
|
||||
previewItem.parentController = parentController;
|
||||
previewItem.allowCaptions = hasCaption;
|
||||
previewItem.hasTimer = hasTimer;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
@class TGMediaSelectionContext;
|
||||
@class TGMediaEditingContext;
|
||||
@class TGSuggestionContext;
|
||||
|
||||
@protocol TGPhotoPaintStickersContext;
|
||||
|
||||
@@ -20,7 +19,6 @@
|
||||
|
||||
@property (nonatomic, readonly) TGMediaSelectionContext *selectionContext;
|
||||
@property (nonatomic, readonly) TGMediaEditingContext *editingContext;
|
||||
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
|
||||
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
||||
|
||||
@property (nonatomic, copy) void (^selectionChanged)(NSUInteger);
|
||||
|
||||
@@ -270,7 +270,7 @@ const CGFloat TGClipboardPreviewEdgeInset = 8.0f;
|
||||
if ([cell isKindOfClass:[TGClipboardPreviewCell class]])
|
||||
thumbnailImage = cell.imageView.image;
|
||||
|
||||
TGClipboardGalleryMixin *mixin = [[TGClipboardGalleryMixin alloc] initWithContext:_context image:image images:_images parentController:self.parentController thumbnailImage:thumbnailImage selectionContext:_selectionContext editingContext:_editingContext suggestionContext:self.suggestionContext stickersContext:self.stickersContext hasCaptions:self.allowCaptions hasTimer:self.hasTimer hasSilentPosting:self.hasSilentPosting hasSchedule:self.hasSchedule reminder:self.reminder recipientName:self.recipientName];
|
||||
TGClipboardGalleryMixin *mixin = [[TGClipboardGalleryMixin alloc] initWithContext:_context image:image images:_images parentController:self.parentController thumbnailImage:thumbnailImage selectionContext:_selectionContext editingContext:_editingContext stickersContext:self.stickersContext hasCaptions:self.allowCaptions hasTimer:self.hasTimer hasSilentPosting:self.hasSilentPosting hasSchedule:self.hasSchedule reminder:self.reminder recipientName:self.recipientName];
|
||||
mixin.presentScheduleController = self.presentScheduleController;
|
||||
mixin.presentTimerController = self.presentTimerController;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#import "LegacyComponentsInternal.h"
|
||||
#import "TGStringUtils.h"
|
||||
#import "TGUser.h"
|
||||
#import "TGLocalization.h"
|
||||
|
||||
static bool value_dateHas12hFormat = false;
|
||||
@@ -455,61 +454,6 @@ static inline NSString *dialogTimeFormat()
|
||||
return [[NSString alloc] initWithFormat:TGLocalized(@"LastSeen.YesterdayAt"), timeString];
|
||||
}
|
||||
|
||||
+ (NSString *)stringForRelativeLastSeen:(int)date
|
||||
{
|
||||
if (date == -1)
|
||||
return TGLocalized(@"Presence.invisible");
|
||||
else if (date == TGUserPresenceValueLately)
|
||||
return TGLocalized(@"LastSeen.Lately");
|
||||
else if (date == TGUserPresenceValueWithinAWeek)
|
||||
return TGLocalized(@"LastSeen.WithinAWeek");
|
||||
else if (date == TGUserPresenceValueWithinAMonth)
|
||||
return TGLocalized(@"LastSeen.WithinAMonth");
|
||||
else if (date == TGUserPresenceValueALongTimeAgo)
|
||||
return TGLocalized(@"LastSeen.ALongTimeAgo");
|
||||
else if (date <= 0)
|
||||
return TGLocalized(@"Presence.offline");
|
||||
|
||||
time_t t = date;
|
||||
struct tm timeinfo;
|
||||
localtime_r(&t, &timeinfo);
|
||||
|
||||
time_t t_now;
|
||||
time(&t_now);
|
||||
struct tm timeinfo_now;
|
||||
localtime_r(&t_now, &timeinfo_now);
|
||||
|
||||
if (timeinfo.tm_year != timeinfo_now.tm_year)
|
||||
return [[NSString alloc] initWithFormat:TGLocalized(@"LastSeen.AtDate"), [self stringForFullDateWithDay:timeinfo.tm_mday month:timeinfo.tm_mon + 1 year:timeinfo.tm_year]];
|
||||
else
|
||||
{
|
||||
int dayDiff = timeinfo.tm_yday - timeinfo_now.tm_yday;
|
||||
|
||||
int minutesDiff = (int)((t_now - date) / 60);
|
||||
int hoursDiff = (int)((t_now - date) / (60 * 60));
|
||||
|
||||
if (dayDiff == 0 && hoursDiff <= 23)
|
||||
{
|
||||
if (minutesDiff < 1)
|
||||
return TGLocalized(@"LastSeen.JustNow");
|
||||
else if (minutesDiff < 60)
|
||||
{
|
||||
return [legacyEffectiveLocalization() getPluralized:@"LastSeen.MinutesAgo" count:(int32_t)minutesDiff];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [legacyEffectiveLocalization() getPluralized:@"LastSeen.HoursAgo" count:(int32_t)hoursDiff];
|
||||
}
|
||||
}
|
||||
else if (dayDiff == -1)
|
||||
return [self stringForLastSeenYesterday:dayDiff == 0 hours:timeinfo.tm_hour minutes:timeinfo.tm_min];
|
||||
else
|
||||
return [[NSString alloc] initWithFormat:TGLocalized(@"LastSeen.AtDate"), [self stringForFullDateWithDay:timeinfo.tm_mday month:timeinfo.tm_mon + 1 year:timeinfo.tm_year]];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSString *)stringForRelativeUpdate:(int)date
|
||||
{
|
||||
time_t t = date;
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
#import "TGGradientLabel.h"
|
||||
|
||||
#import "LegacyComponentsInternal.h"
|
||||
|
||||
@interface TGGradientLabel ()
|
||||
{
|
||||
CGSize _textSize;
|
||||
|
||||
void *_offscreenMemory;
|
||||
int _offscreenContextWidth;
|
||||
int _offscreenContextHeight;
|
||||
int _offscreenContextStride;
|
||||
CGContextRef _offscreenContext;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation TGGradientLabel
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self)
|
||||
{
|
||||
self.opaque = false;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)sizeToFit
|
||||
{
|
||||
if (_text == nil || _font == nil)
|
||||
return;
|
||||
|
||||
_textSize = [self.text boundingRectWithSize:CGSizeMake(1000.0f, 1000.0f) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: _font} context:nil].size;
|
||||
|
||||
CGRect frame = self.frame;
|
||||
frame.size = _textSize;
|
||||
self.frame = frame;
|
||||
}
|
||||
|
||||
- (void)setText:(NSString *)text
|
||||
{
|
||||
NSString *tmpText = text;
|
||||
if (text.length == 1)
|
||||
{
|
||||
unichar c = [text characterAtIndex:0];
|
||||
if (c >= 'a' && c <= 'z')
|
||||
{
|
||||
c += 'A' - 'a';
|
||||
tmpText = [[NSString alloc] initWithCharacters:&c length:1];
|
||||
}
|
||||
}
|
||||
else if (text.length == 3)
|
||||
{
|
||||
unichar c[3] = {[text characterAtIndex:0], [text characterAtIndex:1], [text characterAtIndex:2]};
|
||||
if (c[0] >= 'a' && c[0] <= 'z')
|
||||
c[0] += 'A' - 'a';
|
||||
if (c[2] >= 'a' && c[2] <= 'z')
|
||||
c[2] += 'A' - 'a';
|
||||
|
||||
tmpText = [[NSString alloc] initWithCharacters:c length:3];
|
||||
}
|
||||
_text = tmpText;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)__unused rect
|
||||
{
|
||||
if (_text.length == 0 || _font == nil)
|
||||
return;
|
||||
|
||||
bool nonEmpty = false;
|
||||
for (int i = (int)_text.length - 1; i >= 0; i--)
|
||||
{
|
||||
if ([_text characterAtIndex:i] != ' ')
|
||||
{
|
||||
nonEmpty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nonEmpty)
|
||||
return;
|
||||
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
CGRect bounds = self.bounds;
|
||||
|
||||
if (bounds.size.width < FLT_EPSILON || bounds.size.height < FLT_EPSILON)
|
||||
return;
|
||||
|
||||
int offscreenWidth = (int)bounds.size.width;
|
||||
int offscreenHeight = (int)bounds.size.height;
|
||||
|
||||
if (offscreenWidth != _offscreenContextWidth || offscreenHeight != _offscreenContextHeight)
|
||||
{
|
||||
if (_offscreenMemory != NULL)
|
||||
{
|
||||
free(_offscreenMemory);
|
||||
_offscreenMemory = NULL;
|
||||
}
|
||||
|
||||
if (_offscreenContext != NULL)
|
||||
{
|
||||
CFRelease(_offscreenContext);
|
||||
_offscreenContext = NULL;
|
||||
}
|
||||
|
||||
_offscreenContextWidth = offscreenWidth;
|
||||
_offscreenContextHeight = offscreenHeight;
|
||||
_offscreenContextStride = ((4 * _offscreenContextWidth + 31) & (~31));
|
||||
_offscreenMemory = malloc(_offscreenContextStride * _offscreenContextHeight);
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
|
||||
_offscreenContext = CGBitmapContextCreate(_offscreenMemory, _offscreenContextWidth, _offscreenContextHeight, 8, _offscreenContextStride, colorSpace, bitmapInfo);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
}
|
||||
|
||||
if (_textColor != nil)
|
||||
{
|
||||
CGPoint drawingOffset = CGPointMake(CGFloor((bounds.size.width - _textSize.width) / 2.0f), CGFloor((bounds.size.height - _textSize.height) / 2.0f));
|
||||
|
||||
CGContextSetFillColorWithColor(context, _textColor.CGColor);
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[_text drawAtPoint:drawingOffset withFont:_font];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
else
|
||||
{
|
||||
CGContextSetTextDrawingMode(context, kCGTextClip);
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[_text drawAtPoint:CGPointMake(CGFloor((bounds.size.width - _textSize.width) / 2.0f), CGFloor((bounds.size.height - _textSize.height) / 2.0f)) withFont:_font];
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
CGColorRef colors[2] = {
|
||||
CGColorRetain(UIColorRGB(_topColor).CGColor),
|
||||
CGColorRetain(UIColorRGB(_bottomColor).CGColor)
|
||||
};
|
||||
|
||||
CFArrayRef colorsArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&colors, 2, NULL);
|
||||
CGFloat locations[2] = {0.0f, 1.0f};
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colorsArray, (CGFloat const *)&locations);
|
||||
|
||||
CFRelease(colorsArray);
|
||||
CFRelease(colors[0]);
|
||||
CFRelease(colors[1]);
|
||||
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
|
||||
CGContextDrawLinearGradient(context, gradient, CGPointMake(0.0f, 0.0f), CGPointMake(0.0f, bounds.size.height), 0);
|
||||
|
||||
CFRelease(gradient);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,59 +0,0 @@
|
||||
#import "TGInputTextTag.h"
|
||||
|
||||
#import <CoreText/CoreText.h>
|
||||
|
||||
@implementation TGInputTextTag
|
||||
|
||||
- (instancetype)initWithUniqueId:(int64_t)uniqueId left:(bool)left attachment:(id)attachment {
|
||||
static NSData *imageData = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(1.0f, 1.0f), false, 0.0f);
|
||||
imageData = UIImagePNGRepresentation(UIGraphicsGetImageFromCurrentImageContext());
|
||||
UIGraphicsEndImageContext();
|
||||
});
|
||||
|
||||
self = [super initWithData:imageData ofType:@"public.image"];
|
||||
if (self != nil) {
|
||||
_uniqueId = uniqueId;
|
||||
_left = left;
|
||||
_attachment = attachment;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSTextAttachment *)textAttachment {
|
||||
static UIImage *image = nil;
|
||||
static NSData *imageData = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(1.0f, 1.0f), false, 0.0f);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
|
||||
CGContextFillRect(context, CGRectMake(0.0f, 0.0f, 2.0f, 9.0f));
|
||||
image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
imageData = UIImagePNGRepresentation(image);
|
||||
});
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)__unused textContainer proposedLineFragment:(CGRect)__unused lineFrag glyphPosition:(CGPoint)__unused position characterIndex:(NSUInteger)__unused charIndex {
|
||||
return CGRectZero;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation TGInputTextTagAndRange
|
||||
|
||||
- (instancetype)initWithTag:(TGInputTextTag *)tag range:(NSRange)range {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_tag = tag;
|
||||
_range = range;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,757 +0,0 @@
|
||||
#import "TGItemMenuSheetPreviewView.h"
|
||||
#import "TGMenuSheetView.h"
|
||||
|
||||
#import "LegacyComponentsInternal.h"
|
||||
|
||||
#import <LegacyComponents/TGImageUtils.h>
|
||||
|
||||
#import <LegacyComponents/TGHacks.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import "TGMenuSheetController.h"
|
||||
|
||||
const CGFloat TGItemMenuSheetPreviewLockThreshold = 45.0f;
|
||||
const CGFloat TGItemMenuSheetPreviewLockVelocityThreshold = 800.0f;
|
||||
const CGFloat TGItemMenuSheetPreviewPeekScale = 0.95f;
|
||||
const CGFloat TGItemMenuSheetPreviewArrowVisibleThreshold = -24.0f;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TGItemMenuTransitionTypeSimplified,
|
||||
TGItemMenuTransitionTypeLegacy
|
||||
} TGItemMenuTransitionType;
|
||||
|
||||
@interface TGItemMenuSheetPreviewView () <UIGestureRecognizerDelegate>
|
||||
{
|
||||
UIView *_blurView;
|
||||
UIView *_blurDimView;
|
||||
|
||||
UIImageView *_shadowView;
|
||||
|
||||
UIButton *_dismissButton;
|
||||
|
||||
UIImageView *_arrowView;
|
||||
TGMenuSheetView *_mainSheetView;
|
||||
TGMenuSheetView *_actionsSheetView;
|
||||
|
||||
bool _actionsWerePresented;
|
||||
bool _actionsAnimatingDismiss;
|
||||
|
||||
bool _dismissByVelocity;
|
||||
|
||||
UIPanGestureRecognizer *_panGestureRecognizer;
|
||||
CGPoint _gestureStartLocation;
|
||||
bool _wasPanning;
|
||||
bool _shouldPassPanOffset;
|
||||
TGMenuSheetItemView *_panHandlingItemView;
|
||||
bool _actionsWerePresentedOnGestureStart;
|
||||
|
||||
id<LegacyComponentsContext> _context;
|
||||
TGMenuSheetPallete *_pallete;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation TGItemMenuSheetPreviewView
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context frame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self != nil)
|
||||
{
|
||||
self.clipsToBounds = true;
|
||||
|
||||
_context = context;
|
||||
|
||||
if ([[LegacyComponentsGlobals provider] respondsToSelector:@selector(menuSheetPallete)])
|
||||
_pallete = [[LegacyComponentsGlobals provider] menuSheetPallete];
|
||||
|
||||
TGItemMenuTransitionType type = [self _transitionType];
|
||||
if (type != TGItemMenuTransitionTypeLegacy)
|
||||
{
|
||||
UIBlurEffect *effect = nil;
|
||||
if (type == TGItemMenuTransitionTypeSimplified)
|
||||
effect = _pallete.isDark ? [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark] : [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
|
||||
|
||||
_blurView = [[UIVisualEffectView alloc] initWithEffect:effect];
|
||||
[self addSubview:_blurView];
|
||||
|
||||
if (type == TGItemMenuTransitionTypeSimplified)
|
||||
_blurView.alpha = 0.0f;
|
||||
|
||||
[self.dimView removeFromSuperview];
|
||||
|
||||
_blurDimView = [[UIView alloc] initWithFrame:self.bounds];
|
||||
_blurDimView.alpha = 0.0f;
|
||||
_blurDimView.backgroundColor = UIColorRGBA(0x000000, 0.1f);
|
||||
[self addSubview:_blurDimView];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.dimView.backgroundColor = UIColorRGBA(0x000000, 0.2f);
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context mainItemViews:(NSArray *)mainItemViews actionItemViews:(NSArray *)actionItemViews
|
||||
{
|
||||
self = [self initWithContext:context frame:CGRectZero];
|
||||
if (self != nil)
|
||||
{
|
||||
[self setupWithMainItemViews:mainItemViews actionItemViews:actionItemViews];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupWithMainItemViews:(NSArray *)mainItemViews actionItemViews:(NSArray *)actionItemViews
|
||||
{
|
||||
[self bringSubviewToFront:self.wrapperView];
|
||||
|
||||
[_containerView removeFromSuperview];
|
||||
_containerView = [[UIView alloc] init];
|
||||
[self.wrapperView addSubview:_containerView];
|
||||
|
||||
bool requiresShadow = mainItemViews.count > 0;
|
||||
for (TGMenuSheetItemView *itemView in mainItemViews)
|
||||
{
|
||||
if (itemView.requiresClearBackground)
|
||||
{
|
||||
requiresShadow = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (requiresShadow && _shadowView == nil)
|
||||
{
|
||||
_shadowView = [[UIImageView alloc] init];
|
||||
_shadowView.image = [TGComponentsImageNamed(@"PreviewSheetShadow") resizableImageWithCapInsets:UIEdgeInsetsMake(42.0f, 42.0f, 42.0f, 42.0f)];
|
||||
[_containerView addSubview:_shadowView];
|
||||
}
|
||||
|
||||
[_dismissButton removeFromSuperview];
|
||||
_dismissButton = [[UIButton alloc] initWithFrame:self.bounds];
|
||||
_dismissButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[_dismissButton addTarget:self action:@selector(dismissButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||
[_containerView addSubview:_dismissButton];
|
||||
|
||||
[_mainSheetView removeFromSuperview];
|
||||
|
||||
_mainSheetView = [[TGMenuSheetView alloc] initWithContext:_context pallete:_pallete itemViews:mainItemViews sizeClass:UIUserInterfaceSizeClassCompact dark:false borderless:false];
|
||||
|
||||
__weak TGItemMenuSheetPreviewView *weakSelf = self;
|
||||
void (^menuRelayout)(void) = ^
|
||||
{
|
||||
__strong TGItemMenuSheetPreviewView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
strongSelf->_mainSheetView.frame = [strongSelf _mainViewFrameExpanded:strongSelf.presentActionsImmediately];
|
||||
};
|
||||
_mainSheetView.menuRelayout = menuRelayout;
|
||||
|
||||
[_arrowView removeFromSuperview];
|
||||
_arrowView = [[UIImageView alloc] initWithImage:TGComponentsImageNamed(@"PreviewUpArrow")];
|
||||
_arrowView.alpha = 0.0f;
|
||||
[_mainSheetView addSubview:_arrowView];
|
||||
|
||||
if (actionItemViews.count > 0)
|
||||
{
|
||||
[_actionsSheetView removeFromSuperview];
|
||||
_actionsSheetView = [[TGMenuSheetView alloc] initWithContext:_context pallete:_pallete itemViews:actionItemViews sizeClass:UIUserInterfaceSizeClassCompact dark:false borderless:false];
|
||||
_actionsSheetView.hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setActionItemViews:(NSArray *)__unused actionsView animated:(bool)__unused animated
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (TGItemMenuTransitionType)_transitionType
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
static TGItemMenuTransitionType type;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
CGSize screenSize = TGScreenSize();
|
||||
if (iosMajorVersion() < 8 || (NSInteger)screenSize.height == 480)
|
||||
type = TGItemMenuTransitionTypeLegacy;
|
||||
else
|
||||
type = TGItemMenuTransitionTypeSimplified;
|
||||
});
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
- (void)dismissButtonPressed
|
||||
{
|
||||
[self performDismissal];
|
||||
}
|
||||
|
||||
- (void)prepareSheetViews
|
||||
{
|
||||
CGSize referenceSize = [_context fullscreenBounds].size;
|
||||
CGFloat minSide = MIN(referenceSize.width, referenceSize.height);
|
||||
_mainSheetView.menuWidth = minSide;
|
||||
_actionsSheetView.menuWidth = minSide;
|
||||
|
||||
[_containerView addSubview:_mainSheetView];
|
||||
if (_actionsSheetView != nil)
|
||||
[_containerView addSubview:_actionsSheetView];
|
||||
|
||||
_mainSheetView.frame = [self _mainViewFrameExpanded:self.presentActionsImmediately];
|
||||
_shadowView.frame = [self _shadowFrame];
|
||||
[_mainSheetView layoutSubviews];
|
||||
|
||||
_actionsSheetView.frame = [self _actionsViewFrameExpanded:false];
|
||||
[_actionsSheetView layoutSubviews];
|
||||
|
||||
_arrowView.frame = CGRectMake((_mainSheetView.frame.size.width - _arrowView.frame.size.width) / 2.0f, -14.0f, _arrowView.frame.size.width, _arrowView.frame.size.height);
|
||||
|
||||
[_mainSheetView menuWillAppearAnimated:true];
|
||||
[_actionsSheetView menuWillAppearAnimated:true];
|
||||
}
|
||||
|
||||
- (CGRect)_shadowFrame
|
||||
{
|
||||
CGRect frame = _mainSheetView.frame;
|
||||
frame.origin.x -= 6.5f;
|
||||
frame.size.width += 13.0f;
|
||||
frame.origin.y -= 6.0f;
|
||||
frame.size.height += 13.0f;
|
||||
return frame;
|
||||
}
|
||||
|
||||
- (void)animateAppear
|
||||
{
|
||||
self.wrapperView.frame = self.bounds;
|
||||
|
||||
_containerView.frame = self.wrapperView.bounds;
|
||||
[self prepareSheetViews];
|
||||
|
||||
[super animateAppear];
|
||||
|
||||
void (^completionBlock)(BOOL) = ^(__unused BOOL finished)
|
||||
{
|
||||
if (self.presentActionsImmediately)
|
||||
{
|
||||
[_mainSheetView menuDidAppearAnimated:true];
|
||||
[_actionsSheetView menuDidAppearAnimated:true];
|
||||
|
||||
[self _initializeInternalGestureRecognizer];
|
||||
}
|
||||
};
|
||||
|
||||
if (!self.dontBlurOnPresentation || self.presentActionsImmediately)
|
||||
{
|
||||
[_context setApplicationStatusBarAlpha:0.0f];
|
||||
[self performAppearBackgroundTransition:completionBlock];
|
||||
}
|
||||
|
||||
if (self.presentActionsImmediately)
|
||||
{
|
||||
[self addSubview:_actionsSheetView];
|
||||
[self _presentActions:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)animateDismiss:(void (^)())completion
|
||||
{
|
||||
[self.wrapperView addSubview:_containerView];
|
||||
[super animateDismiss:completion];
|
||||
|
||||
void (^completionBlock)(void) = ^
|
||||
{
|
||||
[_mainSheetView menuDidDisappearAnimated:true];
|
||||
[_actionsSheetView menuDidDisappearAnimated:true];
|
||||
};
|
||||
|
||||
[self performDisappearBackgroundTransition:completionBlock];
|
||||
}
|
||||
|
||||
- (void)performAppearBackgroundTransition:(void (^)(BOOL))completionBlock
|
||||
{
|
||||
TGItemMenuTransitionType type = [self _transitionType];
|
||||
if (type == TGItemMenuTransitionTypeSimplified)
|
||||
{
|
||||
[UIView animateWithDuration:0.22 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^
|
||||
{
|
||||
_blurView.alpha = 1.0f;
|
||||
} completion:completionBlock];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (completionBlock != nil)
|
||||
completionBlock(true);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)performDisappearBackgroundTransition:(void (^)(void))completionBlock
|
||||
{
|
||||
TGItemMenuTransitionType type = [self _transitionType];
|
||||
if (type == TGItemMenuTransitionTypeSimplified)
|
||||
{
|
||||
[UIView animateWithDuration:0.22 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^
|
||||
{
|
||||
[_context setApplicationStatusBarAlpha:1.0f];
|
||||
|
||||
_blurView.alpha = 0.0f;
|
||||
} completion:^(__unused BOOL finished)
|
||||
{
|
||||
completionBlock();
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
[_context setApplicationStatusBarAlpha:1.0f];
|
||||
completionBlock();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_didAppear
|
||||
{
|
||||
[self addSubview:_containerView];
|
||||
|
||||
if (self.presentActionsImmediately || self.isLocked)
|
||||
return;
|
||||
|
||||
[UIView animateWithDuration:0.25 animations:^
|
||||
{
|
||||
_arrowView.alpha = 1.0f;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)_willDisappear
|
||||
{
|
||||
[UIView animateWithDuration:0.16 animations:^
|
||||
{
|
||||
_arrowView.alpha = 0.0f;
|
||||
}];
|
||||
|
||||
[_mainSheetView menuWillDisappearAnimated:true];
|
||||
[_actionsSheetView menuWillDisappearAnimated:true];
|
||||
}
|
||||
|
||||
- (void)setArrowHidden:(bool)hidden animated:(bool)animated
|
||||
{
|
||||
if (animated)
|
||||
{
|
||||
[UIView animateWithDuration:0.25 animations:^
|
||||
{
|
||||
_arrowView.alpha = hidden ? 0.0f : 1.0f;
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
_arrowView.alpha = hidden ? 0.0f : 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_handlePanOffset:(CGFloat)offset
|
||||
{
|
||||
CGFloat centerDelta = [self _mainViewFrameExpanded:false].origin.y - [self _mainViewFrameExpanded:true].origin.y;
|
||||
|
||||
CGFloat appliedOffset = [self swipeOffsetForOffset:offset];
|
||||
|
||||
CGRect frame = [self _mainViewFrameExpanded:_actionsWerePresentedOnGestureStart];
|
||||
frame.origin.y += appliedOffset;
|
||||
_mainSheetView.frame = frame;
|
||||
_shadowView.frame = [self _shadowFrame];
|
||||
|
||||
[self setArrowHidden:(appliedOffset < TGItemMenuSheetPreviewArrowVisibleThreshold || _actionsPresented) animated:true];
|
||||
|
||||
if (!_actionsPresented)
|
||||
{
|
||||
if ((centerDelta > TGItemMenuSheetPreviewLockThreshold && (appliedOffset * -1) > centerDelta) || (centerDelta < TGItemMenuSheetPreviewLockThreshold && (appliedOffset * -1) > TGItemMenuSheetPreviewLockThreshold))
|
||||
{
|
||||
[self _presentActions:nil];
|
||||
}
|
||||
}
|
||||
else if (!_actionsAnimatingDismiss)
|
||||
{
|
||||
CGRect expandedActionsFrame = [self _actionsViewFrameExpanded:true];
|
||||
CGFloat diff = CGRectGetMaxY(_mainSheetView.frame) - 10.0f - CGRectGetMinY(expandedActionsFrame);
|
||||
|
||||
if (diff > 0)
|
||||
{
|
||||
expandedActionsFrame.origin.y += diff;
|
||||
_actionsSheetView.frame = expandedActionsFrame;
|
||||
}
|
||||
|
||||
if (appliedOffset >= 50.0f)
|
||||
[self dismissActions];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_handlePressEnded
|
||||
{
|
||||
[self _initializeInternalGestureRecognizer];
|
||||
|
||||
if (!self.presentActionsImmediately)
|
||||
{
|
||||
[_mainSheetView menuDidAppearAnimated:true];
|
||||
[_actionsSheetView menuDidAppearAnimated:true];
|
||||
}
|
||||
|
||||
[self _centerMainSheetView];
|
||||
}
|
||||
|
||||
- (bool)_maybeLockWithVelocity:(CGFloat)velocity
|
||||
{
|
||||
if (velocity < -TGItemMenuSheetPreviewLockVelocityThreshold)
|
||||
{
|
||||
[self _initializeInternalGestureRecognizer];
|
||||
[self _presentActions:nil];
|
||||
[self _centerMainSheetView];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
- (void)_initializeInternalGestureRecognizer
|
||||
{
|
||||
if (_panGestureRecognizer != nil)
|
||||
return;
|
||||
|
||||
_panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
|
||||
_panGestureRecognizer.delegate = self;
|
||||
[self addGestureRecognizer:_panGestureRecognizer];
|
||||
}
|
||||
|
||||
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
||||
{
|
||||
if (gestureRecognizer == _panGestureRecognizer)
|
||||
{
|
||||
NSString *viewClassName = NSStringFromClass(otherGestureRecognizer.view.class);
|
||||
if ([viewClassName rangeOfString:@"WKScroll"].location != NSNotFound)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
- (void)handlePan:(UIPanGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
CGPoint location = [gestureRecognizer locationInView:self];
|
||||
CGPoint velocity = [gestureRecognizer velocityInView:self];
|
||||
|
||||
CGFloat offset = location.y - _gestureStartLocation.y;
|
||||
|
||||
switch (gestureRecognizer.state)
|
||||
{
|
||||
case UIGestureRecognizerStateBegan:
|
||||
{
|
||||
_actionsWerePresented = _actionsPresented;
|
||||
_actionsWerePresentedOnGestureStart = _actionsPresented;
|
||||
_gestureStartLocation = location;
|
||||
|
||||
_panHandlingItemView = nil;
|
||||
for (TGMenuSheetItemView *itemView in _mainSheetView.itemViews)
|
||||
{
|
||||
if (itemView.handlesPan)
|
||||
{
|
||||
_shouldPassPanOffset = true;
|
||||
_panHandlingItemView = itemView;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case UIGestureRecognizerStateChanged:
|
||||
{
|
||||
bool shouldPan = _shouldPassPanOffset && [_panHandlingItemView passPanOffset:0];
|
||||
if (!shouldPan)
|
||||
{
|
||||
_wasPanning = false;
|
||||
[self _handlePanOffset:0];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_wasPanning)
|
||||
{
|
||||
_gestureStartLocation = location;
|
||||
_wasPanning = true;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_shouldPassPanOffset || shouldPan)
|
||||
[self _handlePanOffset:offset];
|
||||
}
|
||||
break;
|
||||
|
||||
case UIGestureRecognizerStateEnded:
|
||||
case UIGestureRecognizerStateCancelled:
|
||||
{
|
||||
bool allowDismissal = !_shouldPassPanOffset || _wasPanning;
|
||||
if (_actionsPresented && velocity.y < TGItemMenuSheetPreviewLockVelocityThreshold)
|
||||
{
|
||||
[self _centerMainSheetView];
|
||||
}
|
||||
else if (allowDismissal)
|
||||
{
|
||||
_dismissByVelocity = _actionsPresented;
|
||||
[self performDismissal];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)_centerMainSheetView
|
||||
{
|
||||
[self setArrowHidden:_actionsPresented animated:true];
|
||||
|
||||
void (^changeBlock)(void) = ^
|
||||
{
|
||||
_mainSheetView.frame = [self _mainViewFrameExpanded:true];
|
||||
_shadowView.frame = [self _shadowFrame];
|
||||
if (_actionsPresented && !_actionsAnimatingDismiss)
|
||||
_actionsSheetView.frame = [self _actionsViewFrameExpanded:true];
|
||||
};
|
||||
|
||||
void (^completionBlock)(BOOL) = ^(BOOL finished)
|
||||
{
|
||||
if (finished)
|
||||
{
|
||||
if (_actionsSheetView.superview != _containerView)
|
||||
[_containerView addSubview:_actionsSheetView];
|
||||
}
|
||||
};
|
||||
|
||||
if (iosMajorVersion() >= 7)
|
||||
{
|
||||
[UIView animateWithDuration:0.44 delay:0.0 usingSpringWithDamping:0.72f initialSpringVelocity:0.0f options:UIViewAnimationOptionAllowUserInteraction animations:changeBlock completion:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
[UIView animateWithDuration:0.3 delay:0.0 options:0 animations:changeBlock completion:completionBlock];
|
||||
}
|
||||
}
|
||||
|
||||
- (CGRect)_mainViewFrameExpanded:(bool)expanded
|
||||
{
|
||||
CGSize menuSize = _mainSheetView.menuSize;
|
||||
CGRect rect = CGRectMake((_containerView.frame.size.width - menuSize.width) / 2.0f, (_containerView.frame.size.height - menuSize.height) / 2.0f, menuSize.width, menuSize.height);
|
||||
|
||||
if (expanded)
|
||||
{
|
||||
CGRect actionsViewRect = [self _actionsViewFrameExpanded:true];
|
||||
rect.origin.y = MIN(rect.origin.y, actionsViewRect.origin.y - rect.size.height + 10.0f);
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
- (CGRect)_actionsViewFrameExpanded:(bool)expanded
|
||||
{
|
||||
CGSize menuSize = _actionsSheetView.menuSize;
|
||||
CGRect rect = CGRectMake((_containerView.frame.size.width - menuSize.width) / 2.0f, _containerView.frame.size.height, menuSize.width, menuSize.height);
|
||||
|
||||
if (expanded)
|
||||
rect.origin.y = _containerView.frame.size.height - rect.size.height - self.safeAreaInset.bottom;
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
- (CGFloat)swipeOffsetForOffset:(CGFloat)offset
|
||||
{
|
||||
if (offset < 0)
|
||||
return [self rubberBandedOffsetForOffset:offset bandingStart:0.0f coefficient:0.4f range:600.0f];
|
||||
else if ((_actionsPresented || _actionsWerePresented) && offset > 0.0f)
|
||||
return [self rubberBandedOffsetForOffset:offset bandingStart:0.0f coefficient:0.3f range:480.0f];
|
||||
else if (!_actionsPresented && offset > 0.0f)
|
||||
return [self rubberBandedOffsetForOffset:offset bandingStart:0.0f coefficient:0.12f range:320.0f];
|
||||
else
|
||||
return offset;
|
||||
}
|
||||
|
||||
- (CGFloat)rubberBandedOffsetForOffset:(CGFloat)offset bandingStart:(CGFloat)bandingStart coefficient:(CGFloat)coefficient range:(CGFloat)range
|
||||
{
|
||||
CGFloat bandedOffset = offset - bandingStart;
|
||||
return bandingStart + (1.0f - (1.0f / ((bandedOffset * coefficient / range) + 1.0f))) * range;
|
||||
}
|
||||
|
||||
- (void)presentActions:(void (^)(void))animationBlock
|
||||
{
|
||||
[self _initializeInternalGestureRecognizer];
|
||||
|
||||
[self performAppearBackgroundTransition:nil];
|
||||
|
||||
[self addSubview:_actionsSheetView];
|
||||
[self _presentActions:animationBlock];
|
||||
}
|
||||
|
||||
- (void)_presentActions:(void (^)(void))animationBlock
|
||||
{
|
||||
if (_actionsPresented || _actionsAnimatingDismiss)
|
||||
return;
|
||||
|
||||
_actionsPresented = true;
|
||||
_actionsWerePresented = true;
|
||||
_actionsSheetView.hidden = false;
|
||||
|
||||
void (^changeBlock)(void) = ^
|
||||
{
|
||||
_actionsSheetView.frame = [self _actionsViewFrameExpanded:true];
|
||||
if (animationBlock != nil)
|
||||
animationBlock();
|
||||
};
|
||||
|
||||
void (^completionBlock)(BOOL) = ^(BOOL finished)
|
||||
{
|
||||
if (finished)
|
||||
{
|
||||
if (_actionsSheetView.superview != _containerView)
|
||||
[_containerView addSubview:_actionsSheetView];
|
||||
}
|
||||
};
|
||||
|
||||
if (iosMajorVersion() >= 7)
|
||||
{
|
||||
[UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.8f initialSpringVelocity:0.0f options:0 animations:changeBlock completion:completionBlock];
|
||||
}
|
||||
else
|
||||
{
|
||||
[UIView animateWithDuration:0.3 delay:0.0 options:0 animations:changeBlock completion:completionBlock];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dismissActions
|
||||
{
|
||||
_actionsAnimatingDismiss = true;
|
||||
|
||||
void (^changeBlock)(void) = ^
|
||||
{
|
||||
_actionsSheetView.frame = [self _actionsViewFrameExpanded:false];
|
||||
};
|
||||
|
||||
void (^completionBlock)(BOOL) = ^(BOOL finished)
|
||||
{
|
||||
_actionsAnimatingDismiss = false;
|
||||
_actionsPresented = false;
|
||||
_actionsSheetView.hidden = true;
|
||||
|
||||
if (_panGestureRecognizer != nil && _panGestureRecognizer.state != UIGestureRecognizerStateChanged)
|
||||
[self performDismissal];
|
||||
};
|
||||
|
||||
if (iosMajorVersion() >= 7)
|
||||
{
|
||||
[UIView animateWithDuration:0.3 delay:0.0 usingSpringWithDamping:1.5 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowAnimatedContent animations:changeBlock completion:completionBlock];
|
||||
}
|
||||
else
|
||||
{
|
||||
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowAnimatedContent animations:changeBlock completion:completionBlock];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)performCommit
|
||||
{
|
||||
if (self.willDismiss != nil)
|
||||
self.willDismiss();
|
||||
|
||||
void (^changeBlock)(void) = ^
|
||||
{
|
||||
_mainSheetView.frame = CGRectMake(_mainSheetView.frame.origin.x, -_mainSheetView.frame.size.height, _mainSheetView.frame.size.width, _mainSheetView.frame.size.height);
|
||||
_shadowView.frame = [self _shadowFrame];
|
||||
_actionsSheetView.frame = [self _actionsViewFrameExpanded:false];
|
||||
};
|
||||
|
||||
void (^completionBlock)(BOOL) = ^(BOOL finished)
|
||||
{
|
||||
_mainSheetView.hidden = true;
|
||||
_actionsSheetView.hidden = true;
|
||||
[self animateDismiss:^
|
||||
{
|
||||
if (self.onDismiss != nil)
|
||||
self.onDismiss();
|
||||
}];
|
||||
};
|
||||
|
||||
if (iosMajorVersion() >= 7)
|
||||
{
|
||||
[UIView animateWithDuration:0.3 delay:0.0 usingSpringWithDamping:1.5 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowAnimatedContent animations:changeBlock completion:completionBlock];
|
||||
}
|
||||
else
|
||||
{
|
||||
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowAnimatedContent animations:changeBlock completion:completionBlock];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)performDismissal
|
||||
{
|
||||
if (self.willDismiss != nil)
|
||||
self.willDismiss();
|
||||
|
||||
if (_actionsPresented)
|
||||
{
|
||||
[self addSubview:_actionsSheetView];
|
||||
|
||||
void (^changeBlock)(void) = ^
|
||||
{
|
||||
if (!_actionsAnimatingDismiss)
|
||||
_actionsSheetView.frame = [self _actionsViewFrameExpanded:false];
|
||||
|
||||
if (_actionsAnimatingDismiss || _dismissByVelocity)
|
||||
{
|
||||
_mainSheetView.frame = [self _mainViewFrameExpanded:false];
|
||||
_shadowView.frame = [self _shadowFrame];
|
||||
}
|
||||
};
|
||||
|
||||
if (iosMajorVersion() >= 7)
|
||||
{
|
||||
[UIView animateWithDuration:0.24 delay:0.0 usingSpringWithDamping:1.5 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowAnimatedContent animations:changeBlock completion:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
[UIView animateWithDuration:0.2 delay:0.0 options:0 animations:changeBlock completion:nil];
|
||||
}
|
||||
|
||||
TGDispatchAfter(0.15, dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self animateDismiss:^
|
||||
{
|
||||
if (self.onDismiss != nil)
|
||||
self.onDismiss();
|
||||
}];
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
[self animateDismiss:^
|
||||
{
|
||||
if (self.onDismiss != nil)
|
||||
self.onDismiss();
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (bool)isLocked
|
||||
{
|
||||
return _actionsPresented;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
_blurView.frame = self.bounds;
|
||||
_blurDimView.frame = self.bounds;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,152 +0,0 @@
|
||||
#import "TGItemPreviewController.h"
|
||||
|
||||
#import "LegacyComponentsInternal.h"
|
||||
#import "TGViewController.h"
|
||||
|
||||
#import "TGItemPreviewView.h"
|
||||
|
||||
#import "TGOverlayControllerWindow.h"
|
||||
|
||||
@interface TGItemPreviewController ()
|
||||
{
|
||||
bool _autorotationWasEnabled;
|
||||
id<LegacyComponentsContext> _context;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation TGItemPreviewController
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController previewView:(TGItemPreviewView *)previewView
|
||||
{
|
||||
self = [self initWithContext:context];
|
||||
if (self != nil)
|
||||
{
|
||||
_context = context;
|
||||
_previewView = previewView;
|
||||
_previewView.safeAreaInset = [TGViewController safeAreaInsetForOrientation:[LegacyComponentsGlobals provider].applicationStatusBarOrientation hasOnScreenNavigation:false];
|
||||
|
||||
TGOverlayControllerWindow *window = [[TGOverlayControllerWindow alloc] initWithManager:[context makeOverlayWindowManager] parentController:parentController contentController:self keepKeyboard:true];
|
||||
window.windowLevel = UIWindowLevelStatusBar;
|
||||
window.tag = 0xbeef;
|
||||
window.userInteractionEnabled = previewView.userInteractionEnabled;
|
||||
window.hidden = false;
|
||||
|
||||
__weak TGItemPreviewController *weakSelf = self;
|
||||
_previewView.onDismiss = ^
|
||||
{
|
||||
__strong TGItemPreviewController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
[strongSelf dismissImmediately];
|
||||
};
|
||||
|
||||
_previewView.willDismiss = ^{
|
||||
__strong TGItemPreviewController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil && strongSelf.onDismiss != nil)
|
||||
{
|
||||
void (^onDismiss)(void) = [strongSelf.onDismiss copy];
|
||||
strongSelf.onDismiss = nil;
|
||||
onDismiss();
|
||||
}
|
||||
};
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
self.view.frame = [_context fullscreenBounds];
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(NSNotification *)__unused notification
|
||||
{
|
||||
[self.view.window makeKeyAndVisible];
|
||||
}
|
||||
|
||||
- (CGPoint (^)(id))sourcePointForItem
|
||||
{
|
||||
return _previewView.sourcePointForItem;
|
||||
}
|
||||
|
||||
- (void)setSourcePointForItem:(CGPoint (^)(id))sourcePointForItem
|
||||
{
|
||||
_previewView.sourcePointForItem = [sourcePointForItem copy];
|
||||
}
|
||||
|
||||
- (void)loadView
|
||||
{
|
||||
[super loadView];
|
||||
|
||||
_previewView.frame = self.view.bounds;
|
||||
_previewView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[self.view addSubview:_previewView];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[super viewDidAppear:animated];
|
||||
|
||||
_autorotationWasEnabled = [TGViewController autorotationAllowed];
|
||||
[TGViewController disableAutorotation];
|
||||
|
||||
[_previewView animateAppear];
|
||||
}
|
||||
|
||||
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
|
||||
{
|
||||
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
|
||||
|
||||
[self.view.window.layer removeAnimationForKey:@"backgroundColor"];
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:true];
|
||||
self.view.window.layer.backgroundColor = [UIColor clearColor].CGColor;
|
||||
[CATransaction commit];
|
||||
|
||||
for (UIView *view in self.view.window.subviews)
|
||||
{
|
||||
if (view != self.view)
|
||||
{
|
||||
[view removeFromSuperview];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dismiss
|
||||
{
|
||||
if (self.onDismiss != nil)
|
||||
{
|
||||
void (^onDismiss)(void) = [self.onDismiss copy];
|
||||
self.onDismiss = nil;
|
||||
onDismiss();
|
||||
}
|
||||
|
||||
[_previewView animateDismiss:^
|
||||
{
|
||||
[self dismissImmediately];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)_handlePanOffset:(CGFloat)offset
|
||||
{
|
||||
[_previewView _handlePanOffset:offset];
|
||||
}
|
||||
|
||||
- (void)dismissImmediately
|
||||
{
|
||||
[super dismiss];
|
||||
|
||||
if (_autorotationWasEnabled)
|
||||
[TGViewController enableAutorotation];
|
||||
|
||||
if (self.onDismiss != nil)
|
||||
self.onDismiss();
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,147 +0,0 @@
|
||||
#import "TGItemPreviewView.h"
|
||||
|
||||
#import "LegacyComponentsInternal.h"
|
||||
|
||||
@interface TGItemPreviewView ()
|
||||
{
|
||||
bool _disappearing;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation TGItemPreviewView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self != nil)
|
||||
{
|
||||
_dimView = [[UIView alloc] init];
|
||||
_dimView.backgroundColor = [UIColor colorWithWhite:1.0f alpha:0.7f];
|
||||
_dimView.alpha = 0.0f;
|
||||
[self addSubview:_dimView];
|
||||
|
||||
_wrapperView = [[UIView alloc] init];
|
||||
_wrapperView.alpha = 0.0f;
|
||||
[self addSubview:_wrapperView];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)animateAppear
|
||||
{
|
||||
_wrapperView.frame = self.bounds;
|
||||
|
||||
CGPoint transitionInPoint = CGPointZero;
|
||||
if (self.sourcePointForItem != nil)
|
||||
transitionInPoint = self.sourcePointForItem(self.item);
|
||||
|
||||
bool animatedCenter = false;
|
||||
if (!CGPointEqualToPoint(transitionInPoint, CGPointZero))
|
||||
{
|
||||
_wrapperView.center = transitionInPoint;
|
||||
animatedCenter = true;
|
||||
}
|
||||
|
||||
_dimView.alpha = 0.0f;
|
||||
_wrapperView.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
|
||||
|
||||
void (^changeBlock)(void) = ^
|
||||
{
|
||||
_dimView.alpha = 1.0f;
|
||||
_wrapperView.alpha = 1.0f;
|
||||
_wrapperView.transform = CGAffineTransformIdentity;
|
||||
|
||||
if (animatedCenter)
|
||||
_wrapperView.center = [self _wrapperViewContainerCenter];
|
||||
};
|
||||
|
||||
void (^completionBlock)(BOOL) = ^(__unused BOOL finished)
|
||||
{
|
||||
if (finished && !_disappearing)
|
||||
[self _didAppear];
|
||||
};
|
||||
|
||||
if (iosMajorVersion() < 8)
|
||||
{
|
||||
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:changeBlock completion:completionBlock];
|
||||
}
|
||||
else
|
||||
{
|
||||
[UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.72f initialSpringVelocity:0.0f options:0 animations:changeBlock completion:completionBlock];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)animateDismiss:(void (^)())completion
|
||||
{
|
||||
CGPoint transitionOutPoint = CGPointZero;
|
||||
if (self.sourcePointForItem != nil)
|
||||
transitionOutPoint = self.sourcePointForItem(self.item);
|
||||
|
||||
[self _willDisappear];
|
||||
|
||||
_disappearing = true;
|
||||
|
||||
[UIView animateWithDuration:0.2 animations:^
|
||||
{
|
||||
_dimView.alpha = 0.0f;
|
||||
_wrapperView.transform = CGAffineTransformMakeScale(0.3f, 0.3f);
|
||||
_wrapperView.alpha = 0.0f;
|
||||
|
||||
if (!CGPointEqualToPoint(transitionOutPoint, CGPointZero))
|
||||
_wrapperView.center = transitionOutPoint;
|
||||
} completion:^(__unused BOOL finished)
|
||||
{
|
||||
if (completion)
|
||||
completion();
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)_didAppear
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)_willDisappear
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (CGPoint)_wrapperViewContainerCenter
|
||||
{
|
||||
CGRect bounds = self.bounds;
|
||||
|
||||
CGFloat y = bounds.size.height / 2.0f;
|
||||
if (bounds.size.height > bounds.size.width && self.eccentric)
|
||||
y = bounds.size.height / 3.0f;
|
||||
|
||||
return CGPointMake(bounds.size.width / 2.0f, y);
|
||||
}
|
||||
|
||||
- (void)_handlePanOffset:(CGFloat)__unused offset
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)_handlePressEnded
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (bool)_maybeLockWithVelocity:(CGFloat)__unused velocity
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
CGRect previousBounds = _dimView.bounds;
|
||||
if (!CGRectEqualToRect(self.bounds, previousBounds))
|
||||
{
|
||||
_dimView.frame = self.bounds;
|
||||
_wrapperView.center = [self _wrapperViewContainerCenter];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,236 +0,0 @@
|
||||
#import "TGLetteredAvatarView.h"
|
||||
|
||||
#import "LegacyComponentsInternal.h"
|
||||
#import "TGFont.h"
|
||||
#import "TGImageUtils.h"
|
||||
|
||||
#import <LegacyComponents/TGImageManager.h>
|
||||
#import "TGGradientLabel.h"
|
||||
|
||||
@interface TGLetteredAvatarView ()
|
||||
{
|
||||
TGGradientLabel *_label;
|
||||
|
||||
UIFont *_singleFont;
|
||||
UIFont *_doubleFont;
|
||||
bool _usingSingleFont;
|
||||
CGFloat _singleSize;
|
||||
CGFloat _doubleSize;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation TGLetteredAvatarView
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self != nil)
|
||||
{
|
||||
if (@available(iOS 11.0, *)) {
|
||||
self.accessibilityIgnoresInvertColors = true;
|
||||
}
|
||||
|
||||
_label = [[TGGradientLabel alloc] init];
|
||||
_label.backgroundColor = [UIColor clearColor];
|
||||
[self addSubview:_label];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setSingleFontSize:(CGFloat)singleFontSize doubleFontSize:(CGFloat)doubleFontSize useBoldFont:(bool)__unused useBoldFont
|
||||
{
|
||||
if (ABS(singleFontSize - _singleSize) < FLT_EPSILON && ABS(doubleFontSize - _doubleSize) < FLT_EPSILON)
|
||||
return;
|
||||
|
||||
_singleSize = singleFontSize;
|
||||
_doubleSize = doubleFontSize;
|
||||
|
||||
_singleFont = [TGFont roundedFontOfSize:singleFontSize];
|
||||
_doubleFont = _singleFont;
|
||||
}
|
||||
|
||||
- (void)loadImage:(UIImage *)image
|
||||
{
|
||||
_label.hidden = true;
|
||||
|
||||
[super loadImage:image];
|
||||
}
|
||||
|
||||
- (void)loadImage:(NSString *)url filter:(NSString *)filter placeholder:(UIImage *)placeholder forceFade:(bool)forceFade
|
||||
{
|
||||
_label.hidden = true;
|
||||
|
||||
[super loadImage:url filter:filter placeholder:placeholder forceFade:forceFade];
|
||||
}
|
||||
|
||||
static bool isEmojiCharacter(NSString *singleChar)
|
||||
{
|
||||
const unichar high = [singleChar characterAtIndex:0];
|
||||
|
||||
if (0xd800 <= high && high <= 0xdbff && singleChar.length >= 2)
|
||||
{
|
||||
const unichar low = [singleChar characterAtIndex:1];
|
||||
const int codepoint = ((high - 0xd800) * 0x400) + (low - 0xdc00) + 0x10000;
|
||||
|
||||
return (0x1d000 <= codepoint && codepoint <= 0x1f77f);
|
||||
}
|
||||
|
||||
return (0x2100 <= high && high <= 0x27bf);
|
||||
}
|
||||
|
||||
- (NSString *)_cleanedUpString:(NSString *)string
|
||||
{
|
||||
NSMutableString *__block buffer = [NSMutableString stringWithCapacity:string.length];
|
||||
|
||||
[string enumerateSubstringsInRange:NSMakeRange(0, string.length)
|
||||
options:NSStringEnumerationByComposedCharacterSequences
|
||||
usingBlock: ^(NSString* substring, __unused NSRange substringRange, __unused NSRange enclosingRange, __unused BOOL* stop)
|
||||
{
|
||||
[buffer appendString:isEmojiCharacter(substring) ? @"" : substring];
|
||||
}];
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
- (void)setFirstName:(NSString *)firstName lastName:(NSString *)lastName
|
||||
{
|
||||
if (!_label.hidden)
|
||||
{
|
||||
NSString *cleanFirstName = [self _cleanedUpString:firstName];
|
||||
NSString *cleanLastName = [self _cleanedUpString:lastName];
|
||||
|
||||
if (cleanFirstName.length != 0 && cleanLastName.length != 0)
|
||||
_label.text = [[NSString alloc] initWithFormat:@"%@\u200B%@", [cleanFirstName substringToIndex:1], [cleanLastName substringToIndex:1]];
|
||||
else if (cleanFirstName.length != 0)
|
||||
_label.text = [cleanFirstName substringToIndex:1];
|
||||
else if (cleanLastName.length != 0)
|
||||
_label.text = [cleanLastName substringToIndex:1];
|
||||
else
|
||||
_label.text = @" ";
|
||||
|
||||
if (cleanFirstName.length != 0 && cleanLastName.length != 0)
|
||||
{
|
||||
_label.text = [[NSString alloc] initWithFormat:@"%@\u200B%@", [cleanFirstName substringToIndex:1], [cleanLastName substringToIndex:1]];
|
||||
}
|
||||
else if (cleanFirstName.length != 0)
|
||||
{
|
||||
_label.text = [cleanFirstName substringToIndex:1];
|
||||
}
|
||||
else if (cleanLastName.length != 0)
|
||||
{
|
||||
_label.text = [cleanLastName substringToIndex:1];
|
||||
}
|
||||
else
|
||||
_label.text = @" ";
|
||||
|
||||
[_label sizeToFit];
|
||||
CGSize labelSize = _label.frame.size;
|
||||
CGSize boundsSize = self.bounds.size;
|
||||
labelSize.height = boundsSize.height;
|
||||
_label.frame = CGRectMake(TGRetinaFloor((boundsSize.width - labelSize.width) / 2.0f), CGFloor((boundsSize.height - labelSize.height) / 2.0f), labelSize.width, labelSize.height);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTitle:(NSString *)title
|
||||
{
|
||||
NSString *cleanTitle = [self _cleanedUpString:title];
|
||||
_label.text = cleanTitle.length >= 1 ? [cleanTitle substringToIndex:1] : @" ";
|
||||
|
||||
[_label sizeToFit];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setTitleNeedsDisplay
|
||||
{
|
||||
if (!_label.hidden)
|
||||
[_label setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void)loadSavedMessagesWithSize:(CGSize)size placeholder:(UIImage *)placeholder
|
||||
{
|
||||
_label.text = @"";
|
||||
|
||||
NSString *placeholderUri = [[NSString alloc] initWithFormat:@"placeholder://?type=saved-messages&w=%d&h=%d" PRId32 "", (int)size.width, (int)size.height];
|
||||
if (!TGStringCompare([self currentUrl], placeholderUri))
|
||||
[super loadImage:placeholderUri filter:nil placeholder:placeholder];
|
||||
|
||||
_label.hidden = true;
|
||||
}
|
||||
|
||||
- (void)loadUserPlaceholderWithSize:(CGSize)size uid:(int64_t)uid firstName:(NSString *)firstName lastName:(NSString *)lastName placeholder:(UIImage *)placeholder
|
||||
{
|
||||
_label.font = _doubleFont;
|
||||
_usingSingleFont = false;
|
||||
|
||||
NSString *cleanFirstName = [self _cleanedUpString:firstName];
|
||||
NSString *cleanLastName = [self _cleanedUpString:lastName];
|
||||
|
||||
if (cleanFirstName.length != 0 && cleanLastName.length != 0)
|
||||
{
|
||||
_label.text = [[NSString alloc] initWithFormat:@"%@\u200B%@", [cleanFirstName substringToIndex:1], [cleanLastName substringToIndex:1]];
|
||||
}
|
||||
else if (cleanFirstName.length != 0)
|
||||
{
|
||||
_label.text = [cleanFirstName substringToIndex:1];
|
||||
}
|
||||
else if (cleanLastName.length != 0)
|
||||
{
|
||||
_label.text = [cleanLastName substringToIndex:1];
|
||||
}
|
||||
else
|
||||
_label.text = @" ";
|
||||
|
||||
_label.textColor = [UIColor whiteColor];
|
||||
|
||||
[_label sizeToFit];
|
||||
[self setNeedsLayout];
|
||||
|
||||
NSString *placeholderUri = [[NSString alloc] initWithFormat:@"placeholder://?type=user-avatar&w=%d&h=%d&uid=%" PRId32 "", (int)size.width, (int)size.height, (int32_t)uid];
|
||||
if (!TGStringCompare([self currentUrl], placeholderUri))
|
||||
[super loadImage:placeholderUri filter:nil placeholder:placeholder];
|
||||
|
||||
_label.hidden = false;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int top;
|
||||
int bottom;
|
||||
} TGGradientColors;
|
||||
|
||||
- (void)loadGroupPlaceholderWithSize:(CGSize)size conversationId:(int64_t)conversationId title:(NSString *)title placeholder:(UIImage *)placeholder
|
||||
{
|
||||
_label.font = _singleFont;
|
||||
_usingSingleFont = true;
|
||||
|
||||
NSString *cleanTitle = [self _cleanedUpString:title];
|
||||
_label.text = cleanTitle.length >= 1 ? [cleanTitle substringToIndex:1] : @" ";
|
||||
|
||||
if (conversationId == 0)
|
||||
_label.textColor = [UIColor whiteColor];
|
||||
else
|
||||
_label.textColor = [UIColor whiteColor];
|
||||
|
||||
[_label sizeToFit];
|
||||
CGSize labelSize = _label.frame.size;
|
||||
CGSize boundsSize = self.bounds.size;
|
||||
labelSize.height = boundsSize.height;
|
||||
_label.frame = CGRectMake(TGRetinaFloor((boundsSize.width - labelSize.width) / 2.0f), CGFloor((boundsSize.height - labelSize.height) / 2.0f), labelSize.width, labelSize.height);
|
||||
|
||||
[super loadImage:[[NSString alloc] initWithFormat:@"placeholder://?type=group-avatar&w=%d&h=%d&cid=%" PRId64 "", (int)size.width, (int)size.height, conversationId] filter:nil placeholder:placeholder];
|
||||
|
||||
_label.hidden = false;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
CGSize labelSize = _label.frame.size;
|
||||
CGSize boundsSize = self.bounds.size;
|
||||
labelSize.height = boundsSize.height;
|
||||
_label.frame = CGRectMake(TGScreenPixelFloor((boundsSize.width - labelSize.width) / 2.0f), TGScreenPixelFloor((boundsSize.height - labelSize.height) / 2.0f), labelSize.width, labelSize.height);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -246,7 +246,6 @@
|
||||
pickerController = [[TGMediaAssetsPickerController alloc] initWithContext:strongController->_context assetsLibrary:strongController.assetsLibrary assetGroup:group intent:intent selectionContext:inhibitSelection ? nil : strongController->_selectionContext editingContext:strongController->_editingContext saveEditedPhotos:strongController->_saveEditedPhotos];
|
||||
pickerController.pallete = strongController.pallete;
|
||||
}
|
||||
pickerController.suggestionContext = strongController.suggestionContext;
|
||||
pickerController.stickersContext = strongController.stickersContext;
|
||||
pickerController.localMediaCacheEnabled = strongController.localMediaCacheEnabled;
|
||||
pickerController.captionsEnabled = strongController.captionsEnabled;
|
||||
@@ -286,12 +285,6 @@
|
||||
return assetsController;
|
||||
}
|
||||
|
||||
- (void)setSuggestionContext:(TGSuggestionContext *)suggestionContext
|
||||
{
|
||||
_suggestionContext = suggestionContext;
|
||||
self.pickerController.suggestionContext = suggestionContext;
|
||||
}
|
||||
|
||||
- (void)setStickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
||||
{
|
||||
_stickersContext = stickersContext;
|
||||
|
||||
@@ -149,6 +149,18 @@
|
||||
NSUInteger index = [self.selectionContext indexOfItem:(id<TGMediaSelectableItem>)cell.item];
|
||||
[cell.checkButton setNumber:index];
|
||||
}
|
||||
|
||||
NSString *title;
|
||||
if (self.selectionContext.count > 0) {
|
||||
title = [legacyEffectiveLocalization() getPluralized:@"Attachment.SelectedMedia" count:(int32_t)self.selectionContext.count];
|
||||
} else {
|
||||
if (_intent == TGMediaAssetsControllerSendMediaIntent) {
|
||||
title = TGLocalized(@"Attachment.Gallery");
|
||||
} else {
|
||||
title = _assetGroup.title;
|
||||
}
|
||||
}
|
||||
[self setTitle:title];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
@@ -343,9 +355,9 @@
|
||||
};
|
||||
}
|
||||
|
||||
- (TGMediaPickerModernGalleryMixin *)_galleryMixinForContext:(id<LegacyComponentsContext>)context item:(id)item thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities inhibitDocumentCaptions:(bool)inhibitDocumentCaptions asFile:(bool)asFile
|
||||
- (TGMediaPickerModernGalleryMixin *)_galleryMixinForContext:(id<LegacyComponentsContext>)context item:(id)item thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities inhibitDocumentCaptions:(bool)inhibitDocumentCaptions asFile:(bool)asFile
|
||||
{
|
||||
return [[TGMediaPickerModernGalleryMixin alloc] initWithContext:context item:item fetchResult:_fetchResult parentController:self thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext suggestionContext:suggestionContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:self.hasTimer onlyCrop:self.onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:self.inhibitMute asFile:asFile itemsLimit:0 recipientName:self.recipientName hasSilentPosting:self.hasSilentPosting hasSchedule:self.hasSchedule reminder:self.reminder stickersContext:self.stickersContext];
|
||||
return [[TGMediaPickerModernGalleryMixin alloc] initWithContext:context item:item fetchResult:_fetchResult parentController:self thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:self.hasTimer onlyCrop:self.onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:self.inhibitMute asFile:asFile itemsLimit:0 recipientName:self.recipientName hasSilentPosting:self.hasSilentPosting hasSchedule:self.hasSchedule reminder:self.reminder stickersContext:self.stickersContext];
|
||||
}
|
||||
|
||||
- (TGMediaPickerModernGalleryMixin *)galleryMixinForIndexPath:(NSIndexPath *)indexPath previewMode:(bool)previewMode outAsset:(TGMediaAsset **)outAsset
|
||||
@@ -362,7 +374,7 @@
|
||||
|
||||
bool asFile = (_intent == TGMediaAssetsControllerSendFileIntent);
|
||||
|
||||
TGMediaPickerModernGalleryMixin *mixin = [self _galleryMixinForContext:_context item:asset thumbnailImage:thumbnailImage selectionContext:self.selectionContext editingContext:self.editingContext suggestionContext:self.suggestionContext hasCaptions:self.captionsEnabled allowCaptionEntities:self.allowCaptionEntities inhibitDocumentCaptions:self.inhibitDocumentCaptions asFile:asFile];
|
||||
TGMediaPickerModernGalleryMixin *mixin = [self _galleryMixinForContext:_context item:asset thumbnailImage:thumbnailImage selectionContext:self.selectionContext editingContext:self.editingContext hasCaptions:self.captionsEnabled allowCaptionEntities:self.allowCaptionEntities inhibitDocumentCaptions:self.inhibitDocumentCaptions asFile:asFile];
|
||||
mixin.presentScheduleController = self.presentScheduleController;
|
||||
mixin.presentTimerController = self.presentTimerController;
|
||||
__weak TGMediaAssetsPickerController *weakSelf = self;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
@interface TGMediaGroupsController : TGViewController
|
||||
|
||||
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
|
||||
@property (nonatomic, assign) bool localMediaCacheEnabled;
|
||||
@property (nonatomic, assign) bool liveVideoUploadEnabled;
|
||||
@property (nonatomic, assign) bool captionsEnabled;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#import "TGMediaPickerGalleryItem.h"
|
||||
#import "TGModernGallerySelectableItem.h"
|
||||
#import "TGModernGalleryEditableItem.h"
|
||||
|
||||
@interface TGMediaPickerGalleryGifItem : TGMediaPickerGalleryItem <TGModernGallerySelectableItem, TGModernGalleryEditableItem>
|
||||
|
||||
@end
|
||||
@@ -1,37 +0,0 @@
|
||||
#import "TGMediaPickerGalleryGifItem.h"
|
||||
#import "TGMediaPickerGalleryGifItemView.h"
|
||||
|
||||
#import "TGMediaAsset+TGMediaEditableItem.h"
|
||||
|
||||
@implementation TGMediaPickerGalleryGifItem
|
||||
|
||||
@synthesize selectionContext;
|
||||
@synthesize editingContext;
|
||||
@synthesize stickersContext;
|
||||
|
||||
- (NSString *)uniqueId
|
||||
{
|
||||
return self.asset.uniqueIdentifier;
|
||||
}
|
||||
|
||||
- (id<TGMediaSelectableItem>)selectableMediaItem
|
||||
{
|
||||
return self.asset;
|
||||
}
|
||||
|
||||
- (id<TGMediaEditableItem>)editableMediaItem
|
||||
{
|
||||
return self.asset;
|
||||
}
|
||||
|
||||
- (TGPhotoEditorTab)toolbarTabs
|
||||
{
|
||||
return TGPhotoEditorNoneTab;
|
||||
}
|
||||
|
||||
- (Class)viewClass
|
||||
{
|
||||
return [TGMediaPickerGalleryGifItemView class];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,8 +0,0 @@
|
||||
#import <LegacyComponents/TGModernGalleryItemView.h>
|
||||
#import "TGModernGalleryImageItemImageView.h"
|
||||
|
||||
@interface TGMediaPickerGalleryGifItemView : TGModernGalleryItemView
|
||||
|
||||
@property (nonatomic, strong) TGModernGalleryImageItemImageView *imageView;
|
||||
|
||||
@end
|
||||
@@ -1,284 +0,0 @@
|
||||
#import "TGMediaPickerGalleryGifItemView.h"
|
||||
|
||||
#import "LegacyComponentsInternal.h"
|
||||
#import "TGFont.h"
|
||||
#import "TGStringUtils.h"
|
||||
|
||||
#import "TGMediaPickerGalleryGifItem.h"
|
||||
|
||||
#import <LegacyComponents/TGPhotoEditorUtils.h>
|
||||
|
||||
#import "TGModernAnimatedImagePlayer.h"
|
||||
|
||||
#import <LegacyComponents/TGMessageImageViewOverlayView.h>
|
||||
|
||||
#import <LegacyComponents/TGMediaAssetImageSignals.h>
|
||||
#import <LegacyComponents/TGMediaSelectionContext.h>
|
||||
|
||||
@interface TGMediaPickerGalleryGifItemView ()
|
||||
{
|
||||
UIView *_containerView;
|
||||
|
||||
CGSize _imageSize;
|
||||
|
||||
UITapGestureRecognizer *_tapGestureRecognizer;
|
||||
|
||||
SMetaDisposable *_gifDataDisposable;
|
||||
TGModernAnimatedImagePlayer *_player;
|
||||
|
||||
TGMessageImageViewOverlayView *_progressView;
|
||||
bool _progressVisible;
|
||||
void (^_currentAvailabilityObserver)(bool);
|
||||
|
||||
UILabel *_fileInfoLabel;
|
||||
SMetaDisposable *_attributesDisposable;
|
||||
|
||||
bool _imageAvailable;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation TGMediaPickerGalleryGifItemView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self != nil)
|
||||
{
|
||||
_containerView = [[UIView alloc] initWithFrame:self.bounds];
|
||||
_containerView.clipsToBounds = true;
|
||||
[self addSubview:_containerView];
|
||||
|
||||
_imageView = [[TGModernGalleryImageItemImageView alloc] init];
|
||||
[_containerView addSubview:_imageView];
|
||||
|
||||
_fileInfoLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 20)];
|
||||
_fileInfoLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
|
||||
_fileInfoLabel.backgroundColor = [UIColor clearColor];
|
||||
_fileInfoLabel.font = TGSystemFontOfSize(13.0f);
|
||||
_fileInfoLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_fileInfoLabel.textColor = [UIColor whiteColor];
|
||||
|
||||
_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap)];
|
||||
[_containerView addGestureRecognizer:_tapGestureRecognizer];
|
||||
|
||||
_gifDataDisposable = [[SMetaDisposable alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_gifDataDisposable dispose];
|
||||
[_attributesDisposable dispose];
|
||||
}
|
||||
|
||||
- (void)setFrame:(CGRect)frame
|
||||
{
|
||||
[super setFrame:frame];
|
||||
|
||||
if (_containerView == nil)
|
||||
return;
|
||||
|
||||
_containerView.frame = self.bounds;
|
||||
|
||||
[self _layoutPlayerView];
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[_imageView reset];
|
||||
[_player stop];
|
||||
_player = nil;
|
||||
|
||||
_imageAvailable = false;
|
||||
[self setProgressVisible:false value:0.0f animated:false];
|
||||
}
|
||||
|
||||
- (void)setItem:(TGMediaPickerGalleryGifItem *)item synchronously:(bool)synchronously
|
||||
{
|
||||
[super setItem:item synchronously:synchronously];
|
||||
|
||||
_imageSize = item.asset.originalSize;
|
||||
[self _layoutPlayerView];
|
||||
|
||||
if (item.asset == nil)
|
||||
{
|
||||
[self.imageView reset];
|
||||
}
|
||||
else
|
||||
{
|
||||
SSignal *imageSignal = [TGMediaAssetImageSignals imageForAsset:(TGMediaAsset *)item.asset imageType:(item.immediateThumbnailImage != nil) ? TGMediaAssetImageTypeScreen : TGMediaAssetImageTypeFastScreen size:CGSizeMake(1280, 1280)];
|
||||
|
||||
if (item.immediateThumbnailImage != nil)
|
||||
imageSignal = [[SSignal single:item.immediateThumbnailImage] then:imageSignal];
|
||||
|
||||
[self.imageView setSignal:imageSignal];
|
||||
|
||||
__weak TGMediaPickerGalleryGifItemView *weakSelf = self;
|
||||
[_gifDataDisposable setDisposable:[[TGMediaAssetImageSignals imageDataForAsset:(TGMediaAsset *)item.asset] startWithNext:^(id next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryGifItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
if ([next isKindOfClass:[NSNumber class]])
|
||||
{
|
||||
float value = [next floatValue];
|
||||
[strongSelf setProgressVisible:value < 1.0f - FLT_EPSILON value:value animated:true];
|
||||
}
|
||||
else if ([next isKindOfClass:[TGMediaAssetImageData class]])
|
||||
{
|
||||
[strongSelf setProgressVisible:false value:1.0f animated:true];
|
||||
|
||||
TGMediaAssetImageData *data = (TGMediaAssetImageData *)next;
|
||||
[strongSelf _playWithData:data.imageData];
|
||||
|
||||
strongSelf->_imageAvailable = true;
|
||||
if (strongSelf->_currentAvailabilityObserver != nil)
|
||||
strongSelf->_currentAvailabilityObserver(true);
|
||||
}
|
||||
}]];
|
||||
}
|
||||
|
||||
if (!item.asFile)
|
||||
return;
|
||||
|
||||
_fileInfoLabel.text = nil;
|
||||
|
||||
if (_attributesDisposable == nil)
|
||||
_attributesDisposable = [[SMetaDisposable alloc] init];
|
||||
|
||||
__weak TGMediaPickerGalleryGifItemView *weakSelf = self;
|
||||
[_attributesDisposable setDisposable:[[[TGMediaAssetImageSignals fileAttributesForAsset:(TGMediaAsset *)item.asset] deliverOn:[SQueue mainQueue]] startWithNext:^(TGMediaAssetImageFileAttributes *next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryGifItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
NSString *extension = @"GIF";
|
||||
NSString *fileSize = [TGStringUtils stringForFileSize:next.fileSize precision:2];
|
||||
NSString *dimensions = [NSString stringWithFormat:@"%dx%d", (int)next.dimensions.width, (int)next.dimensions.height];
|
||||
|
||||
strongSelf->_fileInfoLabel.text = [NSString stringWithFormat:@"%@ • %@ • %@", extension, fileSize, dimensions];
|
||||
}]];
|
||||
}
|
||||
|
||||
- (void)_playWithData:(NSData *)data
|
||||
{
|
||||
[self.imageView setSignal:nil];
|
||||
|
||||
_player = [[TGModernAnimatedImagePlayer alloc] initWithSize:_imageSize data:data];
|
||||
__weak TGMediaPickerGalleryGifItemView *weakSelf = self;
|
||||
_player.frameReady = ^(UIImage *image)
|
||||
{
|
||||
__strong TGMediaPickerGalleryGifItemView *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
[strongSelf->_imageView loadUri:@"embedded-image://" withOptions:@{TGImageViewOptionEmbeddedImage: image}];
|
||||
};
|
||||
[_player play];
|
||||
}
|
||||
|
||||
- (void)singleTap
|
||||
{
|
||||
if ([self.item conformsToProtocol:@protocol(TGModernGallerySelectableItem)])
|
||||
{
|
||||
TGMediaSelectionContext *selectionContext = ((id<TGModernGallerySelectableItem>)self.item).selectionContext;
|
||||
id<TGMediaSelectableItem> item = ((id<TGModernGallerySelectableItem>)self.item).selectableMediaItem;
|
||||
|
||||
[selectionContext toggleItemSelection:item animated:true sender:nil success:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
id<TGModernGalleryItemViewDelegate> delegate = self.delegate;
|
||||
if ([delegate respondsToSelector:@selector(itemViewDidRequestInterfaceShowHide:)])
|
||||
[delegate itemViewDidRequestInterfaceShowHide:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setProgressVisible:(bool)progressVisible value:(CGFloat)value animated:(bool)animated
|
||||
{
|
||||
_progressVisible = progressVisible;
|
||||
|
||||
if (progressVisible && _progressView == nil)
|
||||
{
|
||||
_progressView = [[TGMessageImageViewOverlayView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 50.0f, 50.0f)];
|
||||
_progressView.userInteractionEnabled = false;
|
||||
|
||||
_progressView.frame = (CGRect){{CGFloor((self.frame.size.width - _progressView.frame.size.width) / 2.0f), CGFloor((self.frame.size.height - _progressView.frame.size.height) / 2.0f)}, _progressView.frame.size};
|
||||
}
|
||||
|
||||
if (progressVisible)
|
||||
{
|
||||
if (_progressView.superview == nil)
|
||||
[_containerView addSubview:_progressView];
|
||||
|
||||
_progressView.alpha = 1.0f;
|
||||
}
|
||||
else if (_progressView.superview != nil)
|
||||
{
|
||||
if (animated)
|
||||
{
|
||||
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^
|
||||
{
|
||||
_progressView.alpha = 0.0f;
|
||||
} completion:^(BOOL finished)
|
||||
{
|
||||
if (finished)
|
||||
[_progressView removeFromSuperview];
|
||||
}];
|
||||
}
|
||||
else
|
||||
[_progressView removeFromSuperview];
|
||||
}
|
||||
|
||||
[_progressView setProgress:value cancelEnabled:false animated:animated];
|
||||
}
|
||||
|
||||
- (SSignal *)contentAvailabilityStateSignal
|
||||
{
|
||||
__weak TGMediaPickerGalleryGifItemView *weakSelf = self;
|
||||
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
|
||||
{
|
||||
__strong TGMediaPickerGalleryGifItemView *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
{
|
||||
[subscriber putNext:@(strongSelf->_imageAvailable)];
|
||||
strongSelf->_currentAvailabilityObserver = ^(bool available)
|
||||
{
|
||||
[subscriber putNext:@(available)];
|
||||
};
|
||||
}
|
||||
|
||||
return nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (UIView *)footerView
|
||||
{
|
||||
if (((TGMediaPickerGalleryItem *)self.item).asFile)
|
||||
return _fileInfoLabel;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)_layoutPlayerView
|
||||
{
|
||||
if (CGSizeEqualToSize(_imageSize, CGSizeZero))
|
||||
return;
|
||||
|
||||
CGSize fittedSize = TGScaleToSize(_imageSize, self.frame.size);
|
||||
|
||||
_imageView.frame = CGRectMake((self.frame.size.width - fittedSize.width) / 2.0f, (self.frame.size.height - fittedSize.height) / 2.0f, fittedSize.width, fittedSize.height);
|
||||
}
|
||||
|
||||
- (UIView *)transitionView
|
||||
{
|
||||
return _containerView;
|
||||
}
|
||||
|
||||
- (CGRect)transitionViewContentRect
|
||||
{
|
||||
return [_imageView convertRect:_imageView.bounds toView:[self transitionView]];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -427,11 +427,6 @@
|
||||
_captionMixin.allowEntities = allowCaptionEntities;
|
||||
}
|
||||
|
||||
- (void)setSuggestionContext:(TGSuggestionContext *)suggestionContext
|
||||
{
|
||||
_captionMixin.suggestionContext = suggestionContext;
|
||||
}
|
||||
|
||||
- (void)setClosePressed:(void (^)())closePressed
|
||||
{
|
||||
_closePressed = [closePressed copy];
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#import "TGModernGalleryEditableItemView.h"
|
||||
#import "TGMediaPickerGalleryItem.h"
|
||||
#import <LegacyComponents/TGModernGalleryZoomableItemView.h>
|
||||
#import "TGMediaPickerGalleryVideoItem.h"
|
||||
#import "TGMediaPickerGalleryVideoItemView.h"
|
||||
|
||||
#import "TGModernMediaListItem.h"
|
||||
@@ -100,12 +101,6 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setSuggestionContext:(TGSuggestionContext *)suggestionContext
|
||||
{
|
||||
_suggestionContext = suggestionContext;
|
||||
[_interfaceView setSuggestionContext:suggestionContext];
|
||||
}
|
||||
|
||||
- (NSInteger)selectionCount
|
||||
{
|
||||
if (self.externalSelectionCount != nil)
|
||||
@@ -185,7 +180,6 @@
|
||||
{
|
||||
__weak TGMediaPickerGalleryModel *weakSelf = self;
|
||||
_interfaceView = [[TGMediaPickerGalleryInterfaceView alloc] initWithContext:_context focusItem:_initialFocusItem selectionContext:_selectionContext editingContext:_editingContext stickersContext:_stickersContext hasSelectionPanel:_hasSelectionPanel hasCameraButton:_hasCamera recipientName:_recipientName];
|
||||
[_interfaceView setSuggestionContext:_suggestionContext];
|
||||
_interfaceView.hasCaptions = _hasCaptions;
|
||||
_interfaceView.allowCaptionEntities = _allowCaptionEntities;
|
||||
_interfaceView.hasTimer = _hasTimer;
|
||||
@@ -410,7 +404,6 @@
|
||||
controller.editingContext = _editingContext;
|
||||
controller.stickersContext = _stickersContext;
|
||||
self.editorController = controller;
|
||||
controller.suggestionContext = self.suggestionContext;
|
||||
controller.willFinishEditing = ^(id<TGMediaEditAdjustments> adjustments, id temporaryRep, bool hasChanges)
|
||||
{
|
||||
__strong TGMediaPickerGalleryModel *strongSelf = weakSelf;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#import <LegacyComponents/TGMediaSelectionContext.h>
|
||||
#import <LegacyComponents/PGPhotoEditorValues.h>
|
||||
|
||||
#import <LegacyComponents/TGMediaPickerGalleryVideoItem.h>
|
||||
|
||||
#import "TGMediaPickerGalleryPhotoItem.h"
|
||||
|
||||
#import "TGPhotoEntitiesContainerView.h"
|
||||
@@ -27,6 +29,7 @@
|
||||
|
||||
@interface TGMediaPickerGalleryPhotoItemView ()
|
||||
{
|
||||
TGMediaPickerGalleryFetchResultItem *_fetchItem;
|
||||
SMetaDisposable *_facesDisposable;
|
||||
|
||||
UILabel *_fileInfoLabel;
|
||||
@@ -123,8 +126,21 @@
|
||||
[self setProgressVisible:false value:0.0f animated:false];
|
||||
}
|
||||
|
||||
- (id<TGModernGalleryItem>)item {
|
||||
if (_fetchItem != nil) {
|
||||
return _fetchItem;
|
||||
} else {
|
||||
return _item;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setItem:(TGMediaPickerGalleryPhotoItem *)item synchronously:(bool)synchronously
|
||||
{
|
||||
if ([item isKindOfClass:[TGMediaPickerGalleryFetchResultItem class]]) {
|
||||
_fetchItem = (TGMediaPickerGalleryFetchResultItem *)item;
|
||||
item = (TGMediaPickerGalleryPhotoItem *)[_fetchItem backingItem];
|
||||
}
|
||||
|
||||
[super setItem:item synchronously:synchronously];
|
||||
|
||||
_entitiesContainerView.stickersContext = item.stickersContext;
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
|
||||
#import "LegacyComponentsInternal.h"
|
||||
|
||||
#import "TGMediaPickerGalleryPhotoItem.h"
|
||||
|
||||
#import "TGMediaPickerGalleryPhotoItemView.h"
|
||||
#import "TGMediaPickerGalleryVideoItemView.h"
|
||||
|
||||
#import <LegacyComponents/TGMediaAssetFetchResult.h>
|
||||
|
||||
#import "TGMediaAsset+TGMediaEditableItem.h"
|
||||
#import "TGCameraCapturedVideo.h"
|
||||
#import <LegacyComponents/AVURLAsset+TGMediaItem.h>
|
||||
@@ -100,3 +105,107 @@
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation TGMediaPickerGalleryFetchResultItem
|
||||
{
|
||||
TGMediaPickerGalleryItem<TGModernGallerySelectableItem, TGModernGalleryEditableItem> *_backingItem;
|
||||
|
||||
TGMediaAssetFetchResult *_fetchResult;
|
||||
NSUInteger _index;
|
||||
}
|
||||
|
||||
@synthesize selectionContext;
|
||||
@synthesize editingContext;
|
||||
@synthesize stickersContext;
|
||||
|
||||
- (instancetype)initWithFetchResult:(TGMediaAssetFetchResult *)fetchResult index:(NSUInteger)index {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_fetchResult = fetchResult;
|
||||
_index = index;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (TGMediaPickerGalleryItem<TGModernGallerySelectableItem, TGModernGalleryEditableItem> *)backingItem {
|
||||
if (_backingItem == nil) {
|
||||
TGMediaAsset *asset = [_fetchResult assetAtIndex:_index];
|
||||
TGMediaPickerGalleryItem<TGModernGallerySelectableItem, TGModernGalleryEditableItem> *backingItem = nil;
|
||||
switch (asset.type)
|
||||
{
|
||||
case TGMediaAssetVideoType:
|
||||
{
|
||||
backingItem = [[TGMediaPickerGalleryVideoItem alloc] initWithAsset:(id<TGMediaEditableItem,TGMediaSelectableItem>)asset];
|
||||
}
|
||||
break;
|
||||
|
||||
case TGMediaAssetGifType:
|
||||
{
|
||||
TGCameraCapturedVideo *convertedAsset = [[TGCameraCapturedVideo alloc] initWithAsset:asset livePhoto:false];
|
||||
backingItem = [[TGMediaPickerGalleryVideoItem alloc] initWithAsset:convertedAsset];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
backingItem = [[TGMediaPickerGalleryPhotoItem alloc] initWithAsset:(id<TGMediaEditableItem,TGMediaSelectableItem>)asset];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
backingItem.selectionContext = self.selectionContext;
|
||||
backingItem.editingContext = self.editingContext;
|
||||
backingItem.stickersContext = self.stickersContext;
|
||||
backingItem.asFile = self.asFile;
|
||||
_backingItem = backingItem;
|
||||
}
|
||||
return _backingItem;
|
||||
}
|
||||
|
||||
- (TGMediaAsset *)asset {
|
||||
return self.backingItem.asset;
|
||||
}
|
||||
|
||||
- (NSString *)uniqueId
|
||||
{
|
||||
if (self.asset != nil)
|
||||
return self.asset.uniqueIdentifier;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id<TGMediaSelectableItem>)selectableMediaItem
|
||||
{
|
||||
if (self.asset != nil)
|
||||
return self.asset;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id<TGMediaEditableItem>)editableMediaItem
|
||||
{
|
||||
if (self.asset != nil)
|
||||
return self.asset;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (TGPhotoEditorTab)toolbarTabs
|
||||
{
|
||||
return self.backingItem.toolbarTabs;
|
||||
}
|
||||
|
||||
- (Class)viewClass
|
||||
{
|
||||
return self.backingItem.viewClass;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
return [object isKindOfClass:[TGMediaPickerGalleryFetchResultItem class]] && (self.backingItem != nil && TGObjectCompare(self.backingItem, ((TGMediaPickerGalleryFetchResultItem *)object).backingItem));
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
|
||||
@interface TGMediaPickerGalleryVideoItemView() <TGMediaPickerGalleryVideoScrubberDataSource, TGMediaPickerGalleryVideoScrubberDelegate>
|
||||
{
|
||||
TGMediaPickerGalleryFetchResultItem *_fetchItem;
|
||||
|
||||
UIView *_containerView;
|
||||
TGModernGalleryVideoContentView *_videoContentView;
|
||||
UIView *_playerWrapperView;
|
||||
@@ -385,6 +387,11 @@
|
||||
|
||||
- (void)setItem:(TGMediaPickerGalleryVideoItem *)item synchronously:(bool)synchronously
|
||||
{
|
||||
if ([item isKindOfClass:[TGMediaPickerGalleryFetchResultItem class]]) {
|
||||
_fetchItem = (TGMediaPickerGalleryFetchResultItem *)item;
|
||||
item = (TGMediaPickerGalleryVideoItem *)[_fetchItem backingItem];
|
||||
}
|
||||
|
||||
bool itemChanged = ![item isEqual:self.item];
|
||||
bool itemIdChanged = item.uniqueId != self.item.uniqueId;
|
||||
|
||||
|
||||
@@ -9,13 +9,11 @@
|
||||
#import "TGMediaPickerGalleryPhotoItem.h"
|
||||
#import "TGMediaPickerGalleryVideoItem.h"
|
||||
#import "TGMediaPickerGalleryVideoItemView.h"
|
||||
#import "TGMediaPickerGalleryGifItem.h"
|
||||
|
||||
#import "TGMediaPickerSendActionSheetController.h"
|
||||
|
||||
#import <LegacyComponents/TGMediaEditingContext.h>
|
||||
#import <LegacyComponents/TGMediaSelectionContext.h>
|
||||
#import <LegacyComponents/TGSuggestionContext.h>
|
||||
|
||||
#import <LegacyComponents/TGMediaAsset.h>
|
||||
#import <LegacyComponents/TGMediaAssetFetchResult.h>
|
||||
@@ -42,17 +40,17 @@
|
||||
|
||||
@implementation TGMediaPickerModernGalleryMixin
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
||||
{
|
||||
return [self initWithContext:context item:item fetchResult:fetchResult momentList:nil parentController:parentController thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext suggestionContext:suggestionContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:hasTimer onlyCrop:onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:inhibitMute asFile:asFile itemsLimit:itemsLimit recipientName:recipientName hasSilentPosting:hasSilentPosting hasSchedule:hasSchedule reminder:reminder stickersContext:stickersContext];
|
||||
return [self initWithContext:context item:item fetchResult:fetchResult momentList:nil parentController:parentController thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:hasTimer onlyCrop:onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:inhibitMute asFile:asFile itemsLimit:itemsLimit recipientName:recipientName hasSilentPosting:hasSilentPosting hasSchedule:hasSchedule reminder:reminder stickersContext:stickersContext];
|
||||
}
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
||||
{
|
||||
return [self initWithContext:context item:item fetchResult:nil momentList:momentList parentController:parentController thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext suggestionContext:suggestionContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:hasTimer onlyCrop:onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:inhibitMute asFile:asFile itemsLimit:itemsLimit recipientName:nil hasSilentPosting:hasSilentPosting hasSchedule:hasSchedule reminder:reminder stickersContext:stickersContext];
|
||||
return [self initWithContext:context item:item fetchResult:nil momentList:momentList parentController:parentController thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:hasTimer onlyCrop:onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:inhibitMute asFile:asFile itemsLimit:itemsLimit recipientName:nil hasSilentPosting:hasSilentPosting hasSchedule:hasSchedule reminder:reminder stickersContext:stickersContext];
|
||||
}
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
@@ -91,7 +89,6 @@
|
||||
model.stickersContext = stickersContext;
|
||||
model.inhibitMute = inhibitMute;
|
||||
model.controller = modernGallery;
|
||||
model.suggestionContext = suggestionContext;
|
||||
model.willFinishEditingItem = ^(id<TGMediaEditableItem> editableItem, id<TGMediaEditAdjustments> adjustments, id representation, bool hasChanges)
|
||||
{
|
||||
__strong TGMediaPickerModernGalleryMixin *strongSelf = weakSelf;
|
||||
@@ -363,34 +360,32 @@
|
||||
|
||||
for (NSUInteger i = 0; i < count; i++)
|
||||
{
|
||||
TGMediaAsset *asset = [fetchResult assetAtIndex:i];
|
||||
|
||||
TGMediaPickerGalleryItem<TGModernGallerySelectableItem, TGModernGalleryEditableItem> *galleryItem = nil;
|
||||
switch (asset.type)
|
||||
{
|
||||
case TGMediaAssetVideoType:
|
||||
{
|
||||
galleryItem = [[TGMediaPickerGalleryVideoItem alloc] initWithAsset:(id<TGMediaEditableItem,TGMediaSelectableItem>)asset];
|
||||
}
|
||||
break;
|
||||
|
||||
case TGMediaAssetGifType:
|
||||
{
|
||||
TGCameraCapturedVideo *convertedAsset = [[TGCameraCapturedVideo alloc] initWithAsset:asset livePhoto:false];
|
||||
galleryItem = [[TGMediaPickerGalleryVideoItem alloc] initWithAsset:convertedAsset];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// if (asset.subtypes & TGMediaAssetSubtypePhotoLive)
|
||||
// galleryItem = [[TGMediaPickerGalleryVideoItem alloc] initWithAsset:asset];
|
||||
// else
|
||||
galleryItem = [[TGMediaPickerGalleryPhotoItem alloc] initWithAsset:(id<TGMediaEditableItem,TGMediaSelectableItem>)asset];
|
||||
}
|
||||
break;
|
||||
}
|
||||
// TGMediaAsset *asset = [fetchResult assetAtIndex:i];
|
||||
//
|
||||
// TGMediaPickerGalleryItem<TGModernGallerySelectableItem, TGModernGalleryEditableItem> *galleryItem = nil;
|
||||
// switch (asset.type)
|
||||
// {
|
||||
// case TGMediaAssetVideoType:
|
||||
// {
|
||||
// galleryItem = [[TGMediaPickerGalleryVideoItem alloc] initWithAsset:(id<TGMediaEditableItem,TGMediaSelectableItem>)asset];
|
||||
// }
|
||||
// break;
|
||||
//
|
||||
// case TGMediaAssetGifType:
|
||||
// {
|
||||
// TGCameraCapturedVideo *convertedAsset = [[TGCameraCapturedVideo alloc] initWithAsset:asset livePhoto:false];
|
||||
// galleryItem = [[TGMediaPickerGalleryVideoItem alloc] initWithAsset:convertedAsset];
|
||||
// }
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// {
|
||||
// galleryItem = [[TGMediaPickerGalleryPhotoItem alloc] initWithAsset:(id<TGMediaEditableItem,TGMediaSelectableItem>)asset];
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
|
||||
TGMediaPickerGalleryFetchResultItem *galleryItem = [[TGMediaPickerGalleryFetchResultItem alloc] initWithFetchResult:fetchResult index:i];
|
||||
galleryItem.selectionContext = selectionContext;
|
||||
galleryItem.editingContext = editingContext;
|
||||
galleryItem.stickersContext = stickersContext;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#import <LegacyComponents/TGObserverProxy.h>
|
||||
|
||||
#import "TGSuggestionContext.h"
|
||||
#import "TGPhotoPaintStickersContext.h"
|
||||
|
||||
@interface TGPhotoCaptionInputMixin ()
|
||||
|
||||
@@ -129,7 +129,6 @@
|
||||
TGMediaPickerGalleryModel *model = [[TGMediaPickerGalleryModel alloc] initWithContext:windowContext items:@[galleryItem] focusItem:galleryItem selectionContext:nil editingContext:editingContext hasCaptions:true allowCaptionEntities:true hasTimer:false onlyCrop:false inhibitDocumentCaptions:false hasSelectionPanel:false hasCamera:false recipientName:recipientName];
|
||||
model.controller = galleryController;
|
||||
model.stickersContext = stickersContext;
|
||||
//model.suggestionContext = self.suggestionContext;
|
||||
|
||||
model.willFinishEditingItem = ^(id<TGMediaEditableItem> editableItem, id<TGMediaEditAdjustments> adjustments, id representation, bool hasChanges)
|
||||
{
|
||||
|
||||
@@ -1,517 +0,0 @@
|
||||
#import "TGRemoteImageView.h"
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
#import "TGCache.h"
|
||||
|
||||
#import <LegacyComponents/SGraphObjectNode.h>
|
||||
|
||||
#import <LegacyComponents/TGImageManager.h>
|
||||
|
||||
static TGCache *sharedCache = nil;
|
||||
|
||||
@interface TGRemoteImageView ()
|
||||
|
||||
@property (atomic, strong) NSString *path;
|
||||
@property (atomic, strong) NSString *currentCacheUrl;
|
||||
|
||||
@property (nonatomic, strong) UIImageView *placeholderView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TGRemoteImageView
|
||||
|
||||
+ (NSMutableDictionary *)imageProcessors
|
||||
{
|
||||
static NSMutableDictionary *dictionary = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
dictionary = [[NSMutableDictionary alloc] init];
|
||||
});
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
+ (NSMutableDictionary *)universalImageProcessors
|
||||
{
|
||||
static NSMutableDictionary *dictionary = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
dictionary = [[NSMutableDictionary alloc] init];
|
||||
});
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
+ (void)throttleDownProcessing
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
+ (void)registerImageUniversalProcessor:(TGImageUniversalProcessor)universalProcessor withBaseName:(NSString *)baseName
|
||||
{
|
||||
[[TGRemoteImageView universalImageProcessors] setObject:[universalProcessor copy] forKey:baseName];
|
||||
}
|
||||
|
||||
+ (void)registerImageProcessor:(TGImageProcessor)imageProcessor withName:(NSString *)name
|
||||
{
|
||||
[[TGRemoteImageView imageProcessors] setObject:[imageProcessor copy] forKey:name];
|
||||
}
|
||||
|
||||
+ (TGImageProcessor)imageProcessorForName:(NSString *)name
|
||||
{
|
||||
TGImageProcessor processor = [[TGRemoteImageView imageProcessors] objectForKey:name];
|
||||
if (processor != nil)
|
||||
return processor;
|
||||
|
||||
NSRange range = [name rangeOfString:@":"];
|
||||
if (range.location != NSNotFound)
|
||||
{
|
||||
NSString *baseName = [name substringToIndex:range.location];
|
||||
TGImageUniversalProcessor universalProcessor = [[TGRemoteImageView universalImageProcessors] objectForKey:baseName];
|
||||
if (universalProcessor != nil)
|
||||
{
|
||||
return ^UIImage *(UIImage *source)
|
||||
{
|
||||
return universalProcessor(name, source);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (void)setSharedCache:(TGCache *)cache
|
||||
{
|
||||
sharedCache = cache;
|
||||
}
|
||||
|
||||
+ (TGCache *)sharedCache
|
||||
{
|
||||
return sharedCache;
|
||||
}
|
||||
|
||||
#pragma mark - Implementation
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self)
|
||||
{
|
||||
_actionHandle = [[ASHandle alloc] initWithDelegate:self releaseOnMainThread:true];
|
||||
_fadeTransitionDuration = 0.14;
|
||||
_useCache = true;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_actionHandle reset];
|
||||
[self cancelLoading];
|
||||
}
|
||||
|
||||
- (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
self.userInteractionEnabled = true;
|
||||
|
||||
[super addGestureRecognizer:gestureRecognizer];
|
||||
}
|
||||
|
||||
- (void)setFadeTransition:(bool)fadeTransition
|
||||
{
|
||||
if (fadeTransition != _fadeTransition)
|
||||
{
|
||||
if (fadeTransition && _placeholderView == nil)
|
||||
{
|
||||
_placeholderView = [[UIImageView alloc] init];
|
||||
_placeholderView.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
|
||||
_placeholderView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[_placeholderView setContentMode:self.contentMode];
|
||||
[self addSubview:_placeholderView];
|
||||
}
|
||||
else if (!fadeTransition && _placeholderView != nil)
|
||||
{
|
||||
[_placeholderView removeFromSuperview];
|
||||
_placeholderView = nil;
|
||||
}
|
||||
|
||||
_fadeTransition = fadeTransition;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setContentMode:(UIViewContentMode)contentMode
|
||||
{
|
||||
if (_placeholderView != nil)
|
||||
[_placeholderView setContentMode:contentMode];
|
||||
|
||||
[super setContentMode:contentMode];
|
||||
}
|
||||
|
||||
- (void)setPlaceholderOverlay:(UIView *)placeholderOverlay
|
||||
{
|
||||
if (_placeholderOverlay != nil)
|
||||
{
|
||||
[_placeholderOverlay removeFromSuperview];
|
||||
_placeholderOverlay = nil;
|
||||
}
|
||||
|
||||
_placeholderOverlay = placeholderOverlay;
|
||||
[_placeholderView addSubview:placeholderOverlay];
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[self cancelLoading];
|
||||
self.image = nil;
|
||||
|
||||
if (_placeholderOverlay != nil)
|
||||
{
|
||||
[_placeholderOverlay removeFromSuperview];
|
||||
_placeholderOverlay = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)prepareForReuse
|
||||
{
|
||||
[self cancelLoading];
|
||||
self.image = nil;
|
||||
}
|
||||
|
||||
- (UIImage *)currentImage
|
||||
{
|
||||
return self.image;
|
||||
}
|
||||
|
||||
- (UIImage *)currentPlaceholderImage
|
||||
{
|
||||
return _placeholderView.image;
|
||||
}
|
||||
|
||||
- (void)tryFillCache:(NSMutableDictionary *)dict
|
||||
{
|
||||
if (_currentUrl == nil)
|
||||
return;
|
||||
|
||||
UIImage *currentImage = [self currentImage];
|
||||
if (currentImage != nil)
|
||||
{
|
||||
NSString *key = _currentFilter == nil ? _currentUrl : [[NSString alloc] initWithFormat:@"{filter:%@}%@", _currentFilter, _currentUrl];
|
||||
|
||||
if (key != nil)
|
||||
[dict setObject:currentImage forKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadImage:(UIImage *)image
|
||||
{
|
||||
[self cancelLoading];
|
||||
|
||||
self.image = image;
|
||||
|
||||
if (_placeholderView != nil)
|
||||
{
|
||||
[_placeholderView.layer removeAllAnimations];
|
||||
_placeholderView.image = nil;
|
||||
_placeholderView.hidden = true;
|
||||
_placeholderView.alpha = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadImage:(NSString *)url filter:(NSString *)filter placeholder:(UIImage *)placeholder
|
||||
{
|
||||
[self loadImage:url filter:filter placeholder:placeholder forceFade:false];
|
||||
}
|
||||
|
||||
- (void)loadImage:(NSString *)url filter:(NSString *)filter placeholder:(UIImage *)placeholder forceFade:(bool)forceFade
|
||||
{
|
||||
[self cancelLoading];
|
||||
|
||||
self.currentUrl = url;
|
||||
self.currentFilter = filter;
|
||||
|
||||
TGCache *cache = _cache != nil ? _cache : [TGRemoteImageView sharedCache];
|
||||
|
||||
NSString *trimmedUrl = url;
|
||||
NSArray *components = [trimmedUrl componentsSeparatedByString:@"_"];
|
||||
if (components.count >= 5)
|
||||
trimmedUrl = [NSString stringWithFormat:@"%@_%@_%@_%@", components[0], components[1], components[2], components[3]];
|
||||
|
||||
NSString *cacheUrl = filter == nil ? trimmedUrl : [[NSString alloc] initWithFormat:@"{filter:%@}%@", filter, trimmedUrl];
|
||||
self.currentCacheUrl = cacheUrl;
|
||||
UIImage *image = [cache cachedImage:cacheUrl availability:TGCacheMemory];
|
||||
|
||||
if (image == nil)
|
||||
image = [[TGImageManager instance] loadImageSyncWithUri:url canWait:false decode:true acceptPartialData:false asyncTaskId:NULL progress:nil partialCompletion:nil completion:nil];
|
||||
|
||||
if (image == nil && (_contentHints & TGRemoteImageContentHintLoadFromDiskSynchronously))
|
||||
{
|
||||
UIImage *managerImage = [[TGImageManager instance] loadImageSyncWithUri:url canWait:true decode:filter == nil acceptPartialData:false asyncTaskId:NULL progress:nil partialCompletion:nil completion:nil];
|
||||
if (managerImage == nil)
|
||||
managerImage = [cache cachedImage:url availability:TGCacheDisk];
|
||||
|
||||
if (managerImage != nil)
|
||||
{
|
||||
if (filter != nil)
|
||||
{
|
||||
TGImageProcessor procesor = [TGRemoteImageView imageProcessorForName:filter];
|
||||
if (procesor != nil)
|
||||
image = procesor(managerImage);
|
||||
}
|
||||
else
|
||||
image = managerImage;
|
||||
}
|
||||
}
|
||||
|
||||
if (image != nil)
|
||||
{
|
||||
if (_contentHints & TGRemoteImageContentHintSaveToGallery)
|
||||
{
|
||||
[ActionStageInstance() requestActor:[[NSString alloc] initWithFormat:@"/tg/checkImageStored/(%lu)", (unsigned long)[url hash]] options:[[NSDictionary alloc] initWithObjectsAndKeys:url, @"url", nil] watcher:self];
|
||||
}
|
||||
|
||||
if (forceFade)
|
||||
{
|
||||
self.image = image;
|
||||
|
||||
if (_placeholderView != nil)
|
||||
{
|
||||
[_placeholderView.layer removeAllAnimations];
|
||||
UIView *placeholderView = _placeholderView;
|
||||
_placeholderView.alpha = 1.0f;
|
||||
_placeholderView.hidden = false;
|
||||
if (placeholder != nil)
|
||||
_placeholderView.image = placeholder;
|
||||
[UIView animateWithDuration:_fadeTransitionDuration animations:^{
|
||||
placeholderView.alpha = 0.0f;
|
||||
} completion:^(BOOL finished)
|
||||
{
|
||||
if (finished)
|
||||
placeholderView.hidden = true;
|
||||
}];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.image = image;
|
||||
|
||||
if (_placeholderView != nil)
|
||||
{
|
||||
[_placeholderView.layer removeAllAnimations];
|
||||
_placeholderView.image = nil;
|
||||
_placeholderView.hidden = true;
|
||||
_placeholderView.alpha = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (_progressHandler)
|
||||
_progressHandler(self, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_allowThumbnailCache)
|
||||
{
|
||||
UIImage *thumbnail = [cache cachedThumbnail:cacheUrl];
|
||||
if (thumbnail != nil)
|
||||
placeholder = thumbnail;
|
||||
}
|
||||
|
||||
if (_placeholderView != nil)
|
||||
{
|
||||
self.image = nil;
|
||||
[_placeholderView.layer removeAllAnimations];
|
||||
_placeholderView.image = placeholder;
|
||||
_placeholderView.hidden = false;
|
||||
_placeholderView.alpha = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.image = placeholder;
|
||||
}
|
||||
|
||||
if (filter != nil)
|
||||
self.path = [NSString stringWithFormat:@"/img/({filter:%@}%@)", filter, url];
|
||||
else
|
||||
self.path = [NSString stringWithFormat:@"/img/(%@)", url];
|
||||
|
||||
NSMutableDictionary *options = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithInt:_cancelTimeout], @"cancelTimeout", cache, @"cache", [NSNumber numberWithBool:_useCache], @"useCache", [NSNumber numberWithBool:_allowThumbnailCache], @"allowThumbnailCache", [[NSNumber alloc] initWithInt:_contentHints], @"contentHints", nil];
|
||||
if (_userProperties != nil)
|
||||
[options setObject:_userProperties forKey:@"userProperties"];
|
||||
if (_contentHints & TGRemoteImageContentHintBlurRemote)
|
||||
options[@"blurIfRemote"] = @(true);
|
||||
[ActionStageInstance() requestActor:self.path options:options watcher:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadPlaceholder:(UIImage *)placeholder
|
||||
{
|
||||
if (!_placeholderView.hidden)
|
||||
_placeholderView.image = placeholder;
|
||||
}
|
||||
|
||||
- (void)cancelLoading
|
||||
{
|
||||
if (self.path != nil)
|
||||
{
|
||||
ASHandle *actionHandle = _actionHandle;
|
||||
NSString *path = self.path;
|
||||
[ActionStageInstance() dispatchOnStageQueue:^
|
||||
{
|
||||
[ActionStageInstance() removeWatcherByHandle:actionHandle fromPath:path];
|
||||
}];
|
||||
|
||||
self.image = nil;
|
||||
|
||||
if (_placeholderView != nil)
|
||||
{
|
||||
[_placeholderView.layer removeAllAnimations];
|
||||
}
|
||||
|
||||
self.path = nil;
|
||||
}
|
||||
|
||||
self.currentUrl = nil;
|
||||
self.currentFilter = nil;
|
||||
}
|
||||
|
||||
+ (UIImage *)imageFromCache:(NSString *)url filter:(NSString *)filter cache:(TGCache *)cache
|
||||
{
|
||||
TGCache *usingCache = cache != nil ? cache : [TGRemoteImageView sharedCache];
|
||||
|
||||
UIImage *image = nil;
|
||||
if (filter == nil)
|
||||
image = [usingCache cachedImage:url availability:TGCacheMemory];
|
||||
else
|
||||
image = [usingCache cachedImage:[[NSString alloc] initWithFormat:@"{filter:%@}%@", filter, url] availability:TGCacheMemory];
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
+ (NSString *)preloadImage:(NSString *)url filter:(NSString *)filter blurIfRemote:(bool)blurIfRemote cache:(TGCache *)cache allowThumbnailCache:(bool)allowThumbnailCache watcher:(id<ASWatcher>)watcher
|
||||
{
|
||||
TGCache *usingCache = cache != nil ? cache : [TGRemoteImageView sharedCache];
|
||||
|
||||
UIImage *image = nil;
|
||||
if (filter == nil)
|
||||
image = [usingCache cachedImage:url availability:TGCacheMemory];
|
||||
else
|
||||
image = [usingCache cachedImage:[[NSString alloc] initWithFormat:@"{filter:%@}%@", filter, url] availability:TGCacheMemory];
|
||||
|
||||
if (image == nil)
|
||||
{
|
||||
NSString *path = nil;
|
||||
if (filter != nil)
|
||||
path = [NSString stringWithFormat:@"/img/({filter:%@}%@)", filter, url];
|
||||
else
|
||||
path = [NSString stringWithFormat:@"/img/(%@)", url];
|
||||
|
||||
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:0], @"cancelTimeout", usingCache, @"cache", [NSNumber numberWithBool:allowThumbnailCache], @"forceMemoryCache", @(TG_CACHE_INPLACE), @"allowThumbnailCache", @(blurIfRemote), @"blurIfRemote", nil];
|
||||
[ActionStageInstance() requestActor:path options:options watcher:watcher];
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)actorMessageReceived:(NSString *)path messageType:(NSString *)messageType message:(id)message
|
||||
{
|
||||
if ([messageType isEqualToString:@"progress"])
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
if (_progressHandler == nil)
|
||||
return;
|
||||
|
||||
if (self.path != nil && [path isEqualToString:self.path])
|
||||
{
|
||||
if (_progressHandler)
|
||||
_progressHandler(self, [message floatValue]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)actorReportedProgress:(NSString *)path progress:(float)progress
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
if (_progressHandler == nil)
|
||||
return;
|
||||
|
||||
if (self.path != nil && [path isEqualToString:self.path])
|
||||
{
|
||||
if (_progressHandler)
|
||||
_progressHandler(self, progress);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)actorCompleted:(int)resultCode path:(NSString *)path result:(id)result
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
if (self.path != nil && [path isEqualToString:self.path])
|
||||
{
|
||||
if (resultCode == ASStatusSuccess && result != nil)
|
||||
{
|
||||
if (_contentHints & TGRemoteImageContentHintSaveToGallery)
|
||||
{
|
||||
[ActionStageInstance() requestActor:[[NSString alloc] initWithFormat:@"/tg/checkImageStored/(%lu)", (unsigned long)[self.currentUrl hash]] options:[[NSDictionary alloc] initWithObjectsAndKeys:self.currentUrl, @"url", nil] watcher:self];
|
||||
}
|
||||
|
||||
UIImage *image = ((SGraphObjectNode *)result).object;
|
||||
if (image != nil)
|
||||
{
|
||||
#if TG_CACHE_INPLACE
|
||||
if (_useCache)
|
||||
{
|
||||
TGCache *cache = _cache != nil ? _cache : [TGRemoteImageView sharedCache];
|
||||
[cache cacheImage:image withData:nil url:self.currentCacheUrl availability:TGCacheMemory];
|
||||
}
|
||||
#endif
|
||||
|
||||
self.image = image;
|
||||
|
||||
if (_placeholderView != nil)
|
||||
{
|
||||
//[_placeholderView.layer removeAllAnimations];
|
||||
if (_fadeTransitionDuration < FLT_EPSILON)
|
||||
{
|
||||
_placeholderView.alpha = 0.0f;
|
||||
_placeholderView.hidden = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
UIView *placeholderView = _placeholderView;
|
||||
[UIView animateWithDuration:_fadeTransitionDuration animations:^
|
||||
{
|
||||
placeholderView.alpha = 0.0f;
|
||||
} completion:^(BOOL finished)
|
||||
{
|
||||
if (finished)
|
||||
placeholderView.hidden = true;
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.currentUrl = nil;
|
||||
self.currentFilter = nil;
|
||||
}
|
||||
|
||||
if (_progressHandler)
|
||||
_progressHandler(self, 1.0f);
|
||||
|
||||
self.path = nil;
|
||||
}
|
||||
/*else if (self.path != nil && ![path isEqualToString:self.path])
|
||||
{
|
||||
TGLegacyLog(@"Received wrong path: <<<%@>>> vs <<<%@>>>", self.path, path);
|
||||
}*/
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,5 +0,0 @@
|
||||
#import "TGSuggestionContext.h"
|
||||
|
||||
@implementation TGSuggestionContext
|
||||
|
||||
@end
|
||||
@@ -1,470 +0,0 @@
|
||||
#import "TGUser.h"
|
||||
|
||||
#import "LegacyComponentsInternal.h"
|
||||
|
||||
#import "TGStringUtils.h"
|
||||
#import "TGPhoneUtils.h"
|
||||
|
||||
#import "NSObject+TGLock.h"
|
||||
|
||||
#import "PSKeyValueCoder.h"
|
||||
|
||||
#import "TGConversation.h"
|
||||
#import "TGMediaOriginInfo.h"
|
||||
#import "TGImageInfo.h"
|
||||
|
||||
typedef enum {
|
||||
TGUserFlagVerified = (1 << 0),
|
||||
TGUserFlagHasExplicitContent = (1 << 1),
|
||||
TGUserFlagIsContextBot = (1 << 2),
|
||||
TGUserFlagMinimalRepresentation = (1 << 3),
|
||||
TGUserFlagBotInlineGeo = (1 << 4)
|
||||
} TGUserFlags;
|
||||
|
||||
@interface TGUser ()
|
||||
{
|
||||
bool _contactIdInitialized;
|
||||
bool _formattedPhoneInitialized;
|
||||
|
||||
TG_SYNCHRONIZED_DEFINE(_cachedValues);
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) NSString *cachedFormattedNumber;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TGUser
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
TG_SYNCHRONIZED_INIT(_cachedValues);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithKeyValueCoder:(PSKeyValueCoder *)coder
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
TG_SYNCHRONIZED_INIT(_cachedValues);
|
||||
_kind = [coder decodeInt32ForCKey:"k"];
|
||||
if (_kind == TGUserKindBot || _kind == TGUserKindSmartBot)
|
||||
{
|
||||
_botInfoVersion = [coder decodeInt32ForCKey:"biv"];
|
||||
_botKind = [coder decodeInt32ForCKey:"bk"];
|
||||
}
|
||||
_flags = [coder decodeInt32ForCKey:"f"];
|
||||
_restrictionReason = [coder decodeStringForCKey:"rr"];
|
||||
if ([self isContextBot]) {
|
||||
_contextBotPlaceholder = [coder decodeStringForCKey:"cbp"];
|
||||
}
|
||||
_about = [coder decodeStringForCKey:"a"];
|
||||
_photoFileReferenceSmall = [coder decodeDataCorCKey:"frs"];
|
||||
_photoFileReferenceBig = [coder decodeDataCorCKey:"frb"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithKeyValueCoder:(PSKeyValueCoder *)coder
|
||||
{
|
||||
[coder encodeInt32:_kind forCKey:"k"];
|
||||
if (_kind == TGUserKindBot || _kind == TGUserKindSmartBot)
|
||||
{
|
||||
[coder encodeInt32:_botInfoVersion forCKey:"biv"];
|
||||
[coder encodeInt32:_botKind forCKey:"bk"];
|
||||
}
|
||||
[coder encodeInt32:_flags forCKey:"f"];
|
||||
[coder encodeString:_restrictionReason forCKey:"rr"];
|
||||
if ([self isContextBot]) {
|
||||
[coder encodeString:_contextBotPlaceholder forCKey:"cbp"];
|
||||
}
|
||||
[coder encodeString:_about forCKey:"a"];
|
||||
[coder encodeData:_photoFileReferenceSmall forCKey:"frs"];
|
||||
[coder encodeData:_photoFileReferenceBig forCKey:"frb"];
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)__unused zone
|
||||
{
|
||||
TGUser *user = [[TGUser alloc] init];
|
||||
|
||||
user.uid = _uid;
|
||||
user.phoneNumber = _phoneNumber;
|
||||
user.phoneNumberHash = _phoneNumberHash;
|
||||
user.firstName = _firstName;
|
||||
user.lastName = _lastName;
|
||||
user.userName = _userName;
|
||||
user.phonebookFirstName = _phonebookFirstName;
|
||||
user.phonebookLastName = _phonebookLastName;
|
||||
user.sex = _sex;
|
||||
user.photoUrlSmall = _photoUrlSmall;
|
||||
user.photoUrlMedium = _photoUrlMedium;
|
||||
user.photoUrlBig = _photoUrlBig;
|
||||
user.photoFileReferenceSmall = _photoFileReferenceSmall;
|
||||
user.photoFileReferenceBig = _photoFileReferenceBig;
|
||||
user.presence = _presence;
|
||||
user.customProperties = _customProperties;
|
||||
user.contactId = _contactId;
|
||||
user->_contactIdInitialized = _contactIdInitialized;
|
||||
user->_formattedPhoneInitialized = _formattedPhoneInitialized;
|
||||
user.cachedFormattedNumber = _cachedFormattedNumber;
|
||||
user->_kind = _kind;
|
||||
user->_botInfoVersion = _botInfoVersion;
|
||||
user->_botKind = _botKind;
|
||||
user->_flags = _flags;
|
||||
user->_restrictionReason = _restrictionReason;
|
||||
user->_contextBotPlaceholder = _contextBotPlaceholder;
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
- (bool)hasAnyName
|
||||
{
|
||||
return _firstName.length != 0 || _lastName.length != 0 || _phonebookFirstName.length != 0 || _phonebookLastName.length != 0;
|
||||
}
|
||||
|
||||
- (bool)isBot {
|
||||
return _kind == TGUserKindBot || _kind == TGUserKindSmartBot;
|
||||
}
|
||||
|
||||
- (bool)isDeleted {
|
||||
return (_phonebookFirstName.length != 0 || _phonebookLastName.length != 0) ? false : ((_firstName.length != 0 || _lastName.length != 0) ? false : (_phoneNumber.length == 0 ? true : false));
|
||||
}
|
||||
|
||||
- (NSString *)firstName
|
||||
{
|
||||
return (_phonebookFirstName.length != 0 || _phonebookLastName.length != 0) ? _phonebookFirstName : ((_firstName.length != 0 || _lastName.length != 0) ? _firstName : (_phoneNumber.length == 0 ? TGLocalized(@"User.DeletedAccount") : [self formattedPhoneNumber]));
|
||||
}
|
||||
|
||||
- (NSString *)lastName
|
||||
{
|
||||
return (_phonebookFirstName.length != 0 || _phonebookLastName.length != 0) ? _phonebookLastName : ((_firstName.length != 0 || _lastName.length != 0) ? _lastName : nil);
|
||||
}
|
||||
|
||||
- (NSString *)realFirstName
|
||||
{
|
||||
return _firstName;
|
||||
}
|
||||
|
||||
- (NSString *)realLastName
|
||||
{
|
||||
return _lastName;
|
||||
}
|
||||
|
||||
- (NSString *)displayName
|
||||
{
|
||||
NSString *firstName = self.firstName;
|
||||
NSString *lastName = self.lastName;
|
||||
|
||||
if (firstName != nil && firstName.length != 0 && lastName != nil && lastName.length != 0)
|
||||
{
|
||||
if (TGIsKorean())
|
||||
return [[NSString alloc] initWithFormat:@"%@ %@", lastName, firstName];
|
||||
else
|
||||
return [[NSString alloc] initWithFormat:@"%@ %@", firstName, lastName];
|
||||
}
|
||||
else if (firstName != nil && firstName.length != 0)
|
||||
return firstName;
|
||||
else if (lastName != nil && lastName.length != 0)
|
||||
return lastName;
|
||||
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSString *)displayRealName
|
||||
{
|
||||
NSString *firstName = self.realFirstName;
|
||||
NSString *lastName = self.realLastName;
|
||||
|
||||
if (firstName != nil && firstName.length != 0 && lastName != nil && lastName.length != 0)
|
||||
return [[NSString alloc] initWithFormat:@"%@ %@", firstName, lastName];
|
||||
else if (firstName != nil && firstName.length != 0)
|
||||
return firstName;
|
||||
else if (lastName != nil && lastName.length != 0)
|
||||
return lastName;
|
||||
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSString *)displayFirstName
|
||||
{
|
||||
NSString *firstName = self.firstName;
|
||||
if (firstName.length != 0)
|
||||
return firstName;
|
||||
|
||||
return self.lastName;
|
||||
}
|
||||
|
||||
- (NSString *)compactName
|
||||
{
|
||||
NSString *firstName = self.firstName;
|
||||
NSString *lastName = self.lastName;
|
||||
|
||||
if (firstName != nil && firstName.length != 0 && lastName != nil && lastName.length != 0)
|
||||
return [[NSString alloc] initWithFormat:@"%@.%@", [firstName substringToIndex:1], lastName];
|
||||
else if (firstName != nil && firstName.length != 0)
|
||||
return firstName;
|
||||
else if (lastName != nil && lastName.length != 0)
|
||||
return lastName;
|
||||
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (void)setPhoneNumber:(NSString *)phoneNumber
|
||||
{
|
||||
TG_SYNCHRONIZED_BEGIN(_cachedValues);
|
||||
_phoneNumber = phoneNumber;
|
||||
_contactIdInitialized = false;
|
||||
_formattedPhoneInitialized = false;
|
||||
TG_SYNCHRONIZED_END(_cachedValues);
|
||||
}
|
||||
|
||||
- (int)contactId
|
||||
{
|
||||
if (!_contactIdInitialized)
|
||||
{
|
||||
int contactId = 0;
|
||||
if (_phoneNumber != nil && _phoneNumber.length != 0)
|
||||
contactId = phoneMatchHash(_phoneNumber);
|
||||
|
||||
TG_SYNCHRONIZED_BEGIN(_cachedValues);
|
||||
_contactId = contactId;
|
||||
_contactIdInitialized = true;
|
||||
TG_SYNCHRONIZED_END(_cachedValues);
|
||||
}
|
||||
|
||||
return _contactId;
|
||||
}
|
||||
|
||||
- (NSString *)formattedPhoneNumber
|
||||
{
|
||||
if (_formattedPhoneInitialized)
|
||||
return _cachedFormattedNumber;
|
||||
else
|
||||
{
|
||||
NSString *cachedFormattedNumber = nil;
|
||||
if (_phoneNumber.length != 0)
|
||||
cachedFormattedNumber = [TGPhoneUtils formatPhone:_phoneNumber forceInternational:true];
|
||||
|
||||
TG_SYNCHRONIZED_BEGIN(_cachedValues);
|
||||
_cachedFormattedNumber = cachedFormattedNumber;
|
||||
_formattedPhoneInitialized = true;
|
||||
TG_SYNCHRONIZED_END(_cachedValues);
|
||||
|
||||
return cachedFormattedNumber;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
return [object isKindOfClass:[TGUser class]] && [self isEqualToUser:object];
|
||||
}
|
||||
|
||||
- (bool)isEqualToUser:(TGUser *)anotherUser
|
||||
{
|
||||
if (anotherUser.uid == _uid &&
|
||||
((anotherUser.realFirstName == nil && _firstName == nil) || [anotherUser.realFirstName isEqualToString:_firstName]) &&
|
||||
((anotherUser.realLastName == nil && _lastName == nil) || [anotherUser.realLastName isEqualToString:_lastName]) &&
|
||||
anotherUser.sex == _sex &&
|
||||
((anotherUser.phonebookFirstName == nil && _phonebookFirstName == nil) || [anotherUser.phonebookFirstName isEqualToString:_phonebookFirstName]) &&
|
||||
((anotherUser.phonebookLastName == nil && _phonebookLastName == nil) || [anotherUser.phonebookLastName isEqualToString:_phonebookLastName]) &&
|
||||
((anotherUser.phoneNumber == nil && _phoneNumber == nil) || [anotherUser.phoneNumber isEqualToString:_phoneNumber]) &&
|
||||
anotherUser.phoneNumberHash == _phoneNumberHash &&
|
||||
((anotherUser.photoUrlSmall == nil && _photoUrlSmall == nil) || [anotherUser.photoUrlSmall isEqualToString:_photoUrlSmall]) &&
|
||||
((anotherUser.photoUrlMedium == nil && _photoUrlMedium == nil) || [anotherUser.photoUrlMedium isEqualToString:_photoUrlMedium]) &&
|
||||
((anotherUser.photoUrlBig == nil && _photoUrlBig == nil) || [anotherUser.photoUrlBig isEqualToString:_photoUrlBig]) && TGObjectCompare(anotherUser.photoFileReferenceSmall, _photoFileReferenceSmall) && TGObjectCompare(anotherUser.photoFileReferenceBig, _photoFileReferenceBig) && anotherUser.presence.online == _presence.online && anotherUser.presence.lastSeen == _presence.lastSeen && TGStringCompare(_userName, anotherUser.userName) && anotherUser.kind == _kind && anotherUser.botKind == _botKind &&
|
||||
TGStringCompare(_restrictionReason, anotherUser.restrictionReason))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
- (int)differenceFromUser:(TGUser *)anotherUser
|
||||
{
|
||||
int difference = 0;
|
||||
|
||||
if (_uid != anotherUser.uid)
|
||||
difference |= TGUserFieldUid;
|
||||
|
||||
if ((_phoneNumber == nil) != (anotherUser.phoneNumber == nil) || (_phoneNumber != nil && ![_phoneNumber isEqualToString:anotherUser.phoneNumber]))
|
||||
difference |= TGUserFieldPhoneNumber;
|
||||
|
||||
if (_phoneNumberHash != anotherUser.phoneNumberHash)
|
||||
difference |= TGUserFieldPhoneNumberHash;
|
||||
|
||||
if ((_firstName == nil) != (anotherUser.realFirstName == nil) || (_firstName != nil && ![_firstName isEqualToString:anotherUser.realFirstName]))
|
||||
difference |= TGUserFieldFirstName;
|
||||
|
||||
if ((_lastName == nil) != (anotherUser.realLastName == nil) || (_lastName != nil && ![_lastName isEqualToString:anotherUser.realLastName]))
|
||||
difference |= TGUserFieldLastName;
|
||||
|
||||
if (!TGStringCompare(_userName, anotherUser.userName))
|
||||
difference |= TGUserFieldUsername;
|
||||
|
||||
if ((_phonebookFirstName == nil) != (anotherUser.phonebookFirstName == nil) || (_phonebookFirstName != nil && ![_phonebookFirstName isEqualToString:anotherUser.phonebookFirstName]))
|
||||
difference |= TGUserFieldPhonebookFirstName;
|
||||
|
||||
if ((_phonebookLastName == nil) != (anotherUser.phonebookLastName == nil) || (_phonebookLastName != nil && ![_phonebookLastName isEqualToString:anotherUser.phonebookLastName]))
|
||||
difference |= TGUserFieldPhonebookLastName;
|
||||
|
||||
if (_sex != anotherUser.sex)
|
||||
difference |= TGUserFieldSex;
|
||||
|
||||
if ((_photoUrlSmall == nil) != (anotherUser.photoUrlSmall == nil) || (_photoUrlSmall != nil && ![_photoUrlSmall isEqualToString:anotherUser.photoUrlSmall]))
|
||||
difference |= TGUserFieldPhotoUrlSmall;
|
||||
|
||||
if ((_photoUrlMedium == nil) != (anotherUser.photoUrlMedium == nil) || (_photoUrlMedium != nil && ![_photoUrlMedium isEqualToString:anotherUser.photoUrlMedium]))
|
||||
difference |= TGUserFieldPhotoUrlMedium;
|
||||
|
||||
if ((_photoUrlBig == nil) != (anotherUser.photoUrlBig == nil) || (_photoUrlBig != nil && ![_photoUrlBig isEqualToString:anotherUser.photoUrlBig]))
|
||||
difference |= TGUserFieldPhotoUrlBig;
|
||||
|
||||
if (_presence.lastSeen != anotherUser.presence.lastSeen)
|
||||
difference |= TGUserFieldPresenceLastSeen;
|
||||
|
||||
if (_presence.online != anotherUser.presence.online)
|
||||
difference |= TGUserFieldPresenceOnline;
|
||||
|
||||
if (anotherUser.kind != _kind)
|
||||
difference |= TGUserFieldOther;
|
||||
|
||||
if (anotherUser.botKind != _botKind)
|
||||
difference |= TGUserFieldOther;
|
||||
|
||||
if (anotherUser.flags != _flags) {
|
||||
difference |= TGUserFieldOther;
|
||||
}
|
||||
|
||||
if (!TGStringCompare(anotherUser.restrictionReason, _restrictionReason)) {
|
||||
difference |= TGUserFieldOther;
|
||||
}
|
||||
|
||||
if (!TGStringCompare(anotherUser.contextBotPlaceholder, _contextBotPlaceholder)) {
|
||||
difference |= TGUserFieldOther;
|
||||
}
|
||||
|
||||
return difference;
|
||||
}
|
||||
|
||||
+ (TGUserPresence)approximatePresenceFromPresence:(TGUserPresence)presence currentTime:(NSTimeInterval)currentTime
|
||||
{
|
||||
if (presence.lastSeen <= 0)
|
||||
return presence;
|
||||
|
||||
if (presence.lastSeen >= (int)(currentTime - 60 * 60 * 24 * 4))
|
||||
return (TGUserPresence){.online = false, .lastSeen = TGUserPresenceValueLately, .temporaryLastSeen = 0};
|
||||
else if (presence.lastSeen >= (int)(currentTime - 60 * 60 * 24 * 4))
|
||||
return (TGUserPresence){.online = false, .lastSeen = TGUserPresenceValueWithinAWeek, .temporaryLastSeen = 0};
|
||||
else if (presence.lastSeen >= (int)(currentTime - 60 * 60 * 24 * 31))
|
||||
return (TGUserPresence){.online = false, .lastSeen = TGUserPresenceValueWithinAMonth, .temporaryLastSeen = 0};
|
||||
|
||||
return (TGUserPresence){.online = false, .lastSeen = TGUserPresenceValueALongTimeAgo, .temporaryLastSeen = 0};
|
||||
}
|
||||
|
||||
- (bool)isVerified {
|
||||
return _flags & TGUserFlagVerified;
|
||||
}
|
||||
|
||||
- (void)setIsVerified:(bool)isVerified {
|
||||
if (isVerified) {
|
||||
_flags |= TGUserFlagVerified;
|
||||
} else {
|
||||
_flags &= ~TGUserFlagVerified;
|
||||
}
|
||||
}
|
||||
|
||||
- (bool)isContextBot {
|
||||
return _flags & TGUserFlagIsContextBot;
|
||||
}
|
||||
|
||||
- (void)setIsContextBot:(bool)isContextBot {
|
||||
if (isContextBot) {
|
||||
_flags |= TGUserFlagIsContextBot;
|
||||
} else {
|
||||
_flags &= ~TGUserFlagIsContextBot;
|
||||
}
|
||||
}
|
||||
|
||||
- (bool)hasExplicitContent {
|
||||
return _flags & TGConversationFlagHasExplicitContent;
|
||||
}
|
||||
|
||||
- (void)setHasExplicitContent:(bool)hasExplicitContent {
|
||||
if (hasExplicitContent) {
|
||||
_flags |= TGConversationFlagHasExplicitContent;
|
||||
} else {
|
||||
_flags &= ~TGConversationFlagHasExplicitContent;
|
||||
}
|
||||
}
|
||||
|
||||
- (bool)minimalRepresentation {
|
||||
return _flags & TGUserFlagMinimalRepresentation;
|
||||
}
|
||||
|
||||
- (void)setMinimalRepresentation:(bool)minimalRepresentation {
|
||||
if (minimalRepresentation) {
|
||||
_flags |= TGUserFlagMinimalRepresentation;
|
||||
} else {
|
||||
_flags &= ~TGUserFlagMinimalRepresentation;
|
||||
}
|
||||
}
|
||||
|
||||
- (bool)botInlineGeo {
|
||||
return _flags & TGUserFlagBotInlineGeo;
|
||||
}
|
||||
|
||||
- (void)setBotInlineGeo:(bool)botInlineGeo {
|
||||
if (botInlineGeo) {
|
||||
_flags |= TGUserFlagBotInlineGeo;
|
||||
} else {
|
||||
_flags &= ~TGUserFlagBotInlineGeo;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)photoFullUrlSmall
|
||||
{
|
||||
NSString *finalAvatarUrl = self.photoUrlSmall;
|
||||
if (finalAvatarUrl.length == 0)
|
||||
return finalAvatarUrl;
|
||||
|
||||
int64_t volumeId = 0;
|
||||
int32_t localId = 0;
|
||||
if (extractFileUrlComponents(self.photoUrlSmall, NULL, &volumeId, &localId, NULL))
|
||||
{
|
||||
NSString *key = [NSString stringWithFormat:@"%lld_%d", volumeId, localId];
|
||||
NSDictionary *fileReferences = nil;
|
||||
if (self.photoFileReferenceSmall != nil) {
|
||||
fileReferences = @{ key: self.photoFileReferenceSmall };
|
||||
}
|
||||
TGMediaOriginInfo *originInfo = [TGMediaOriginInfo mediaOriginInfoWithFileReference:self.photoFileReferenceSmall fileReferences:fileReferences userId:_uid offset:0];
|
||||
finalAvatarUrl = [finalAvatarUrl stringByAppendingFormat:@"_o%@", [originInfo stringRepresentation]];
|
||||
}
|
||||
|
||||
return finalAvatarUrl;
|
||||
}
|
||||
|
||||
- (NSString *)photoFullUrlBig
|
||||
{
|
||||
NSString *finalAvatarUrl = self.photoUrlBig;
|
||||
if (finalAvatarUrl.length == 0)
|
||||
return finalAvatarUrl;
|
||||
|
||||
int64_t volumeId = 0;
|
||||
int32_t localId = 0;
|
||||
if (extractFileUrlComponents(self.photoUrlBig, NULL, &volumeId, &localId, NULL))
|
||||
{
|
||||
NSString *key = [NSString stringWithFormat:@"%lld_%d", volumeId, localId];
|
||||
NSDictionary *fileReferences = nil;
|
||||
if (self.photoFileReferenceBig != nil) {
|
||||
fileReferences = @{ key: self.photoFileReferenceBig };
|
||||
}
|
||||
TGMediaOriginInfo *originInfo = [TGMediaOriginInfo mediaOriginInfoWithFileReference:self.photoFileReferenceBig fileReferences:fileReferences userId:_uid offset:0];
|
||||
finalAvatarUrl = [finalAvatarUrl stringByAppendingFormat:@"_o%@", [originInfo stringRepresentation]];
|
||||
}
|
||||
|
||||
return finalAvatarUrl;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -23,7 +23,6 @@ swift_library(
|
||||
"//submodules/LocalMediaResources:LocalMediaResources",
|
||||
"//submodules/SearchPeerMembers:SearchPeerMembers",
|
||||
"//submodules/SaveToCameraRoll:SaveToCameraRoll",
|
||||
"//submodules/LegacyMediaPickerUI/LegacyImageProcessors:LegacyImageProcessors",
|
||||
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
|
||||
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
|
||||
"//submodules/StickerResources:StickerResources",
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
|
||||
objc_library(
|
||||
name = "LegacyImageProcessors",
|
||||
enable_modules = True,
|
||||
module_name = "LegacyImageProcessors",
|
||||
srcs = glob([
|
||||
"Sources/**/*.m",
|
||||
"Sources/**/*.h",
|
||||
]),
|
||||
hdrs = glob([
|
||||
"PublicHeaders/**/*.h",
|
||||
]),
|
||||
includes = [
|
||||
"PublicHeaders",
|
||||
],
|
||||
deps = [
|
||||
"//submodules/LegacyComponents:LegacyComponents",
|
||||
],
|
||||
sdk_frameworks = [
|
||||
"Foundation",
|
||||
"UIKit",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
||||
@@ -1,5 +0,0 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface LegacyImageProcessors : NSObject
|
||||
|
||||
@end
|
||||
@@ -1,56 +0,0 @@
|
||||
#import <LegacyImageProcessors/LegacyImageProcessors.h>
|
||||
|
||||
#import <LegacyComponents/LegacyComponents.h>
|
||||
|
||||
@implementation LegacyImageProcessors
|
||||
|
||||
+ (void)load {
|
||||
[TGRemoteImageView registerImageUniversalProcessor:^UIImage *(NSString *name, UIImage *source) {
|
||||
CGSize size = CGSizeZero;
|
||||
int n = 7;
|
||||
bool invalid = false;
|
||||
for (int i = n; i < (int)name.length; i++) {
|
||||
unichar c = [name characterAtIndex:i];
|
||||
if (c == 'x')
|
||||
{
|
||||
if (i == n)
|
||||
invalid = true;
|
||||
else
|
||||
{
|
||||
size.width = [[name substringWithRange:NSMakeRange(n, i - n)] intValue];
|
||||
n = i + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (c < '0' || c > '9')
|
||||
{
|
||||
invalid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!invalid)
|
||||
{
|
||||
for (int i = n; i < (int)name.length; i++)
|
||||
{
|
||||
unichar c = [name characterAtIndex:i];
|
||||
if (c < '0' || c > '9')
|
||||
{
|
||||
invalid = true;
|
||||
break;
|
||||
}
|
||||
else if (i == (int)name.length - 1)
|
||||
{
|
||||
size.height = [[name substringFromIndex:n] intValue];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!invalid)
|
||||
{
|
||||
return TGScaleAndRoundCornersWithOffsetAndFlags(source, size, CGPointZero, size, (int)size.width / 2, nil, false, nil, TGScaleImageScaleSharper);
|
||||
}
|
||||
|
||||
return nil;
|
||||
} withBaseName:@"circle"];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -187,7 +187,6 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, chatLocati
|
||||
let carouselItem = TGAttachmentCarouselItemView(context: parentController.context, camera: PGCamera.cameraAvailable(), selfPortrait: false, forProfilePhoto: false, assetType: TGMediaAssetAnyType, saveEditedPhotos: !isSecretChat && saveEditedPhotos, allowGrouping: editMediaOptions == nil && allowGrouping, allowSelection: editMediaOptions == nil, allowEditing: true, document: false, selectionLimit: selectionLimit)!
|
||||
carouselItemView = carouselItem
|
||||
carouselItem.stickersContext = paintStickersContext
|
||||
carouselItem.suggestionContext = legacySuggestionContext(context: context, peerId: peer.id, chatLocation: chatLocation)
|
||||
carouselItem.recipientName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
var openedCamera = false
|
||||
controller.willDismiss = { [weak carouselItem] _ in
|
||||
@@ -474,8 +473,6 @@ public func presentLegacyPasteMenu(context: AccountContext, peer: Peer, chatLoca
|
||||
let recipientName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
|
||||
legacyController.enableSizeClassSignal = true
|
||||
|
||||
let suggestionContext = legacySuggestionContext(context: context, peerId: peer.id, chatLocation: chatLocation)
|
||||
|
||||
let paintStickersContext = LegacyPaintStickersContext(context: context)
|
||||
paintStickersContext.captionPanelView = {
|
||||
@@ -489,7 +486,7 @@ public func presentLegacyPasteMenu(context: AccountContext, peer: Peer, chatLoca
|
||||
})
|
||||
}
|
||||
|
||||
let controller = TGClipboardMenu.present(inParentController: emptyController, context: legacyController.context, images: images, allowGrouping: allowGrouping, hasCaption: true, hasTimer: hasTimer, hasSilentPosting: hasSilentPosting, hasSchedule: hasSchedule, reminder: peer.id == context.account.peerId, recipientName: recipientName, suggestionContext: suggestionContext, stickersContext: paintStickersContext, presentScheduleController: { done in
|
||||
let controller = TGClipboardMenu.present(inParentController: emptyController, context: legacyController.context, images: images, allowGrouping: allowGrouping, hasCaption: true, hasTimer: hasTimer, hasSilentPosting: hasSilentPosting, hasSchedule: hasSchedule, reminder: peer.id == context.account.peerId, recipientName: recipientName, stickersContext: paintStickersContext, presentScheduleController: { done in
|
||||
presentSchedulePicker { time in
|
||||
done?(time)
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ public func configureLegacyAssetPicker(_ controller: TGMediaAssetsController, co
|
||||
controller.captionsEnabled = captionsEnabled
|
||||
controller.inhibitDocumentCaptions = false
|
||||
controller.stickersContext = paintStickersContext
|
||||
controller.suggestionContext = legacySuggestionContext(context: context, peerId: peer.id, chatLocation: chatLocation)
|
||||
if peer.id != context.account.peerId {
|
||||
if peer is TelegramUser {
|
||||
controller.hasTimer = hasSchedule
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import TelegramCore
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
import LegacyComponents
|
||||
import LegacyUI
|
||||
import SearchPeerMembers
|
||||
import AccountContext
|
||||
|
||||
public func legacySuggestionContext(context: AccountContext, peerId: PeerId, chatLocation: ChatLocation) -> TGSuggestionContext {
|
||||
let suggestionContext = TGSuggestionContext()
|
||||
suggestionContext.userListSignal = { query in
|
||||
return SSignal { subscriber in
|
||||
if let query = query {
|
||||
let disposable = searchPeerMembers(context: context, peerId: peerId, chatLocation: chatLocation, query: query, scope: .mention).start(next: { peers in
|
||||
let users = NSMutableArray()
|
||||
for peer in peers {
|
||||
if case let .user(peer) = peer {
|
||||
let user = TGUser()
|
||||
user.uid = peer.id.id._internalGetInt64Value()
|
||||
user.firstName = peer.firstName
|
||||
user.lastName = peer.lastName
|
||||
user.userName = peer.addressName
|
||||
if let representation = smallestImageRepresentation(peer.photo) {
|
||||
user.photoUrlSmall = legacyImageLocationUri(resource: representation.resource)
|
||||
}
|
||||
users.add(user)
|
||||
}
|
||||
}
|
||||
|
||||
subscriber.putNext(users)
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
|
||||
return SBlockDisposable {
|
||||
disposable.dispose()
|
||||
}
|
||||
} else {
|
||||
subscriber.putNext(NSArray())
|
||||
subscriber.putCompletion()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
suggestionContext.hashtagListSignal = { query in
|
||||
return SSignal { subscriber in
|
||||
let disposable = (context.engine.messages.recentlyUsedHashtags() |> map { hashtags -> [String] in
|
||||
let normalizedQuery = query?.lowercased()
|
||||
var result: [String] = []
|
||||
if let normalizedQuery = normalizedQuery {
|
||||
for hashtag in hashtags {
|
||||
if hashtag.lowercased().hasPrefix(normalizedQuery) {
|
||||
result.append(hashtag)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { hashtags in
|
||||
subscriber.putNext(hashtags)
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
|
||||
return SBlockDisposable {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
suggestionContext.alphacodeSignal = { query, inputLanguageCode in
|
||||
guard let query = query, let inputLanguageCode = inputLanguageCode else {
|
||||
return SSignal.complete()
|
||||
}
|
||||
return SSignal { subscriber in
|
||||
let disposable = (context.engine.stickers.searchEmojiKeywords(inputLanguageCode: inputLanguageCode, query: query, completeMatch: query.count < 3)
|
||||
|> map { keywords -> [TGAlphacodeEntry] in
|
||||
var result: [TGAlphacodeEntry] = []
|
||||
for keyword in keywords {
|
||||
for emoticon in keyword.emoticons {
|
||||
result.append(TGAlphacodeEntry(emoji: emoticon, code: keyword.keyword))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}).start(next: { result in
|
||||
subscriber.putNext(result)
|
||||
subscriber.putCompletion()
|
||||
}, error: nil, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
|
||||
return SBlockDisposable {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
return suggestionContext
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import LegacyComponents
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import SwiftSignalKit
|
||||
|
||||
final class LegacyImageDownloadActor: ASActor {
|
||||
private let disposable = MetaDisposable()
|
||||
|
||||
deinit {
|
||||
self.disposable.dispose()
|
||||
}
|
||||
|
||||
override static func genericPath() -> String! {
|
||||
return "/img/@";
|
||||
}
|
||||
|
||||
override func execute(_ options: [AnyHashable : Any]!) {
|
||||
let actualPath = self.path as NSString
|
||||
|
||||
var url: String
|
||||
var processor: TGImageProcessor?
|
||||
var cacheUrl: String
|
||||
if actualPath.hasPrefix("/img/({filter:") {
|
||||
let range = actualPath.range(of: "}")
|
||||
if range.location == NSNotFound {
|
||||
ActionStageInstance().nodeRetrieveFailed(self.path)
|
||||
return
|
||||
}
|
||||
|
||||
let processorName = actualPath.substring(with: NSMakeRange(14, range.location - 14))
|
||||
processor = TGRemoteImageView.imageProcessor(forName: processorName)
|
||||
url = actualPath.substring(with: NSMakeRange(range.location + 1, actualPath.length - range.location - 1 - 1))
|
||||
cacheUrl = "{filter:\(processorName)}\(url)"
|
||||
}
|
||||
else {
|
||||
url = actualPath.substring(with: NSMakeRange(6, actualPath.length - 6 - 1))
|
||||
cacheUrl = url
|
||||
}
|
||||
|
||||
if url.hasPrefix("placeholder://") {
|
||||
let path = self.path
|
||||
let token = TGImageManager.instance().beginLoadingImageAsync(withUri: url, decode: true, progress: nil, partialCompletion: nil, completion: { image in
|
||||
ActionStageInstance().actionCompleted(path, result: SGraphObjectNode(object: image))
|
||||
})
|
||||
let disposable = ActionDisposable {
|
||||
TGImageManager.instance().cancelTask(withId: token)
|
||||
}
|
||||
self.disposable.set(disposable)
|
||||
} else if let resource = resourceFromLegacyImageUri(url) {
|
||||
let disposables = DisposableSet()
|
||||
self.disposable.set(disposables)
|
||||
if let account = legacyContextGet()?.account {
|
||||
let path = self.path
|
||||
disposables.add(account.postbox.mediaBox.resourceData(resource).start(next: { data in
|
||||
if data.complete {
|
||||
ActionStageInstance().globalStageDispatchQueue().async {
|
||||
if let image = UIImage(contentsOfFile: data.path) {
|
||||
var updatedImage: UIImage? = image
|
||||
if let processor = processor {
|
||||
updatedImage = processor(image)
|
||||
}
|
||||
TGRemoteImageView.sharedCache().cacheImage(updatedImage, with: nil, url: cacheUrl, availability: Int32(TGCacheMemory.rawValue))
|
||||
ActionStageInstance().actionCompleted(path, result: SGraphObjectNode(object: updatedImage))
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
disposables.add(account.postbox.mediaBox.fetchedResource(resource, parameters: nil).start())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func cancel() {
|
||||
self.disposable.dispose()
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
|
||||
public func legacyImageLocationUri(resource: MediaResource) -> String? {
|
||||
if let resource = resource as? CloudPeerPhotoSizeMediaResource {
|
||||
return resource.id.stringRepresentation
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
private let legacyImageUriExpr = try? NSRegularExpression(pattern: "telegram-peer-photo-size-([-\\d]+)-([-\\d]+)-([-\\d]+)-([-\\d]+)-([-\\d]+)", options: [])
|
||||
|
||||
public func resourceFromLegacyImageUri(_ uri: String) -> MediaResource? {
|
||||
guard let legacyImageUriExpr = legacyImageUriExpr else {
|
||||
return nil
|
||||
}
|
||||
let matches = legacyImageUriExpr.matches(in: uri, options: [], range: NSRange(location: 0, length: uri.count))
|
||||
if let match = matches.first {
|
||||
let nsString = uri as NSString
|
||||
let datacenterId = nsString.substring(with: match.range(at: 1))
|
||||
let photoId = nsString.substring(with: match.range(at: 2))
|
||||
let size = nsString.substring(with: match.range(at: 3))
|
||||
let volumeId = nsString.substring(with: match.range(at: 4))
|
||||
let localId = nsString.substring(with: match.range(at: 5))
|
||||
|
||||
guard let nDatacenterId = Int32(datacenterId) else {
|
||||
return nil
|
||||
}
|
||||
guard let nPhotoId = Int64(photoId) else {
|
||||
return nil
|
||||
}
|
||||
guard let nSizeSpec = Int32(size), let sizeSpec = CloudPeerPhotoSizeSpec(rawValue: nSizeSpec) else {
|
||||
return nil
|
||||
}
|
||||
guard let nVolumeId = Int64(volumeId) else {
|
||||
return nil
|
||||
}
|
||||
guard let nLocalId = Int32(localId) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return CloudPeerPhotoSizeMediaResource(datacenterId: nDatacenterId, photoId: nPhotoId, sizeSpec: sizeSpec, volumeId: nVolumeId, localId: nLocalId)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import LegacyComponents
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import SwiftSignalKit
|
||||
import Display
|
||||
|
||||
private let gradientColors: [NSArray] = [
|
||||
[UIColor(rgb: 0xff516a).cgColor, UIColor(rgb: 0xff885e).cgColor],
|
||||
[UIColor(rgb: 0xffa85c).cgColor, UIColor(rgb: 0xffcd6a).cgColor],
|
||||
[UIColor(rgb: 0x54cb68).cgColor, UIColor(rgb: 0xa0de7e).cgColor],
|
||||
[UIColor(rgb: 0x2a9ef1).cgColor, UIColor(rgb: 0x72d5fd).cgColor],
|
||||
[UIColor(rgb: 0x665fff).cgColor, UIColor(rgb: 0x82b1ff).cgColor],
|
||||
[UIColor(rgb: 0xd669ed).cgColor, UIColor(rgb: 0xe0a2f3).cgColor]
|
||||
]
|
||||
|
||||
private let grayscaleColors: NSArray = [
|
||||
UIColor(rgb: 0xefefef).cgColor, UIColor(rgb: 0xeeeeee).cgColor
|
||||
]
|
||||
|
||||
private let sharedImageCache = TGMemoryImageCache(softMemoryLimit: 2 * 1024 * 1024, hardMemoryLimit: 3 * 1024 * 1024)!
|
||||
|
||||
final class LegacyPeerAvatarPlaceholderDataSource: TGImageDataSource {
|
||||
private let account: () -> Account?
|
||||
|
||||
init(account: @escaping () -> Account?) {
|
||||
self.account = account
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
override func canHandleUri(_ uri: String!) -> Bool {
|
||||
if let uri = uri {
|
||||
if uri.hasPrefix("placeholder://") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override func loadDataSync(withUri uri: String!, canWait: Bool, acceptPartialData: Bool, asyncTaskId: AutoreleasingUnsafeMutablePointer<AnyObject?>!, progress: ((Float) -> Void)!, partialCompletion: ((TGDataResource?) -> Void)!, completion: ((TGDataResource?) -> Void)!) -> TGDataResource! {
|
||||
if let image = sharedImageCache.image(forKey: uri, attributes: nil) {
|
||||
return TGDataResource(image: image, decoded: true)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
override func loadDataAsync(withUri uri: String!, progress: ((Float) -> Void)!, partialCompletion: ((TGDataResource?) -> Void)!, completion: ((TGDataResource?) -> Void)!) -> Any! {
|
||||
if let account = self.account() {
|
||||
let signal: Signal<Never, NoError> = Signal { subscriber in
|
||||
let args: [AnyHashable : Any]
|
||||
let argumentsString = String(uri[uri.index(uri.startIndex, offsetBy: "placeholder://?".count)...])
|
||||
args = TGStringUtils.argumentDictionary(inUrlString: argumentsString)!
|
||||
|
||||
guard let width = Int((args["w"] as! String)), width > 1 else {
|
||||
return EmptyDisposable
|
||||
}
|
||||
guard let height = Int((args["h"] as! String)), height > 1 else {
|
||||
return EmptyDisposable
|
||||
}
|
||||
|
||||
var peerId = PeerId(0)
|
||||
|
||||
if let uid = args["uid"] as? String, let nUid = Int64(uid) {
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(nUid))
|
||||
} else if let cid = args["cid"] as? String, let nCid = Int64(cid) {
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(nCid))
|
||||
}
|
||||
|
||||
let image = generateImage(CGSize(width: CGFloat(width), height: CGFloat(height)), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.beginPath()
|
||||
context.addEllipse(in: CGRect(x: 0.0, y: 0.0, width: size.width, height:
|
||||
size.height))
|
||||
context.clip()
|
||||
|
||||
let colorIndex: Int
|
||||
if peerId.id._internalGetInt64Value() == 0 {
|
||||
colorIndex = -1
|
||||
} else {
|
||||
colorIndex = abs(Int(clamping: account.peerId.id._internalGetInt64Value() &+ peerId.id._internalGetInt64Value()))
|
||||
}
|
||||
|
||||
let colorsArray: NSArray
|
||||
if colorIndex == -1 {
|
||||
colorsArray = grayscaleColors
|
||||
} else {
|
||||
colorsArray = gradientColors[colorIndex % gradientColors.count]
|
||||
}
|
||||
|
||||
var locations: [CGFloat] = [1.0, 0.2];
|
||||
|
||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||
let gradient = CGGradient(colorsSpace: colorSpace, colors: colorsArray, locations: &locations)!
|
||||
|
||||
context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
||||
|
||||
context.setBlendMode(.normal)
|
||||
})
|
||||
|
||||
sharedImageCache.setImage(image, forKey: uri, attributes: nil)
|
||||
completion?(TGDataResource(image: image, decoded: true))
|
||||
|
||||
subscriber.putCompletion()
|
||||
|
||||
return EmptyDisposable
|
||||
}
|
||||
|
||||
return (signal |> runOn(Queue.concurrentDefaultQueue())).start()
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
override func cancelTask(byId taskId: Any!) {
|
||||
if let disposable = taskId as? Disposable {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,11 +314,5 @@ public func initializeLegacyComponents(application: UIApplication?, currentSizeC
|
||||
|
||||
freedomInit()
|
||||
|
||||
TGRemoteImageView.setSharedCache(TGCache())
|
||||
|
||||
TGImageDataSource.register(LegacyPeerAvatarPlaceholderDataSource(account: {
|
||||
return legacyContext?.account
|
||||
}))
|
||||
ASActor.registerClass(LegacyImageDownloadActor.self)
|
||||
LegacyComponentsGlobals.setProvider(LegacyComponentsGlobalsProviderImpl())
|
||||
}
|
||||
|
||||
@@ -81,7 +81,6 @@ func presentedLegacyCamera(context: AccountContext, peer: Peer, chatLocation: Ch
|
||||
controller.allowCaptionEntities = true
|
||||
controller.allowGrouping = mediaGrouping
|
||||
controller.inhibitDocumentCaptions = false
|
||||
controller.suggestionContext = legacySuggestionContext(context: context, peerId: peer.id, chatLocation: chatLocation)
|
||||
controller.recipientName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
if peer.id != context.account.peerId {
|
||||
if peer is TelegramUser {
|
||||
|
||||
@@ -6,6 +6,13 @@ import TelegramPresentationData
|
||||
import LegacyUI
|
||||
import PhoneNumberFormat
|
||||
|
||||
private func legacyImageLocationUri(resource: MediaResource) -> String? {
|
||||
if let resource = resource as? CloudPeerPhotoSizeMediaResource {
|
||||
return resource.id.stringRepresentation
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func makePeerIdFromBridgeIdentifier(_ identifier: Int64) -> PeerId? {
|
||||
if identifier < 0 && identifier > Int32.min {
|
||||
return PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(-identifier))
|
||||
|
||||
@@ -340,9 +340,6 @@ func presentLegacyWebSearchGallery(context: AccountContext, peer: EnginePeer?, c
|
||||
|
||||
let model = TGMediaPickerGalleryModel(context: legacyController.context, items: items, focus: focusItem, selectionContext: selectionContext, editingContext: editingContext, hasCaptions: false, allowCaptionEntities: true, hasTimer: false, onlyCrop: false, inhibitDocumentCaptions: false, hasSelectionPanel: false, hasCamera: false, recipientName: peer?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))!
|
||||
model.stickersContext = paintStickersContext
|
||||
if let peer = peer, let chatLocation = chatLocation {
|
||||
model.suggestionContext = legacySuggestionContext(context: context, peerId: peer.id, chatLocation: chatLocation)
|
||||
}
|
||||
controller.model = model
|
||||
model.controller = controller
|
||||
model.useGalleryImageAsEditableItemImage = true
|
||||
|
||||
Reference in New Issue
Block a user