mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-04-07 13:47:54 +00:00
Fixes
fix localeWithStrings globally (#30)
Fix badge on zoomed devices. closes #9
Hide channel bottom panel closes #27
Another attempt to fix badge on some Zoomed devices
Force System Share sheet tg://sg/debug
fixes for device badge
New Crowdin updates (#34)
* New translations sglocalizable.strings (Chinese Traditional)
* New translations sglocalizable.strings (Chinese Simplified)
* New translations sglocalizable.strings (Chinese Traditional)
Fix input panel hidden on selection (#31)
* added if check for selectionState != nil
* same order of subnodes
Revert "Fix input panel hidden on selection (#31)"
This reverts commit e8a8bb1496.
Fix input panel for channels Closes #37
Quickly share links with system's share menu
force tabbar when editing
increase height for correct animation
New translations sglocalizable.strings (Ukrainian) (#38)
Hide Post Story button
Fix 10.15.1
Fix archive option for long-tap
Enable in-app Safari
Disable some unsupported purchases
disableDeleteChatSwipeOption + refactor restart alert
Hide bot in suggestions list
Fix merge v11.0
Fix exceptions for safari webview controller
New Crowdin updates (#47)
* New translations sglocalizable.strings (Romanian)
* New translations sglocalizable.strings (French)
* New translations sglocalizable.strings (Spanish)
* New translations sglocalizable.strings (Afrikaans)
* New translations sglocalizable.strings (Arabic)
* New translations sglocalizable.strings (Catalan)
* New translations sglocalizable.strings (Czech)
* New translations sglocalizable.strings (Danish)
* New translations sglocalizable.strings (German)
* New translations sglocalizable.strings (Greek)
* New translations sglocalizable.strings (Finnish)
* New translations sglocalizable.strings (Hebrew)
* New translations sglocalizable.strings (Hungarian)
* New translations sglocalizable.strings (Italian)
* New translations sglocalizable.strings (Japanese)
* New translations sglocalizable.strings (Korean)
* New translations sglocalizable.strings (Dutch)
* New translations sglocalizable.strings (Norwegian)
* New translations sglocalizable.strings (Polish)
* New translations sglocalizable.strings (Portuguese)
* New translations sglocalizable.strings (Serbian (Cyrillic))
* New translations sglocalizable.strings (Swedish)
* New translations sglocalizable.strings (Turkish)
* New translations sglocalizable.strings (Vietnamese)
* New translations sglocalizable.strings (Indonesian)
* New translations sglocalizable.strings (Hindi)
* New translations sglocalizable.strings (Uzbek)
New Crowdin updates (#49)
* New translations sglocalizable.strings (Arabic)
* New translations sglocalizable.strings (Arabic)
New translations sglocalizable.strings (Russian) (#51)
Call confirmation
WIP Settings search
Settings Search
Localize placeholder
Update AccountUtils.swift
mark mutual contact
Align back context action to left
New Crowdin updates (#54)
* New translations sglocalizable.strings (Chinese Simplified)
* New translations sglocalizable.strings (Chinese Traditional)
* New translations sglocalizable.strings (Ukrainian)
Independent Playground app for simulator
New translations sglocalizable.strings (Ukrainian) (#55)
Playground UIKit base and controllers
Inject SwiftUI view with overflow to AsyncDisplayKit
Launch Playgound project on simulator
Create .swiftformat
Move Playground to example
Update .swiftformat
Init SwiftUIViewController
wip
New translations sglocalizable.strings (Chinese Traditional) (#57)
Xcode 16 fixes
Fix
New translations sglocalizable.strings (Italian) (#59)
New translations sglocalizable.strings (Chinese Simplified) (#63)
Force disable CallKit integration due to missing NSE Entitlement
Fix merge
Fix whole chat translator
Sweetpad config
Bump version
11.3.1 fixes
Mutual contact placement fix
Disable Video PIP swipe
Update versions.json
Fix PIP crash
1875 lines
74 KiB
Objective-C
1875 lines
74 KiB
Objective-C
#import "TGMediaPickerGalleryInterfaceView.h"
|
|
|
|
#import "LegacyComponentsInternal.h"
|
|
#import "TGImageUtils.h"
|
|
#import "TGFont.h"
|
|
|
|
#import <SSignalKit/SSignalKit.h>
|
|
|
|
#import <LegacyComponents/TGPhotoEditorUtils.h>
|
|
#import <LegacyComponents/TGObserverProxy.h>
|
|
|
|
#import <LegacyComponents/TGModernButton.h>
|
|
#import <LegacyComponents/TGMenuSheetController.h>
|
|
|
|
#import <LegacyComponents/TGMediaSelectionContext.h>
|
|
#import <LegacyComponents/TGMediaEditingContext.h>
|
|
#import <LegacyComponents/TGVideoEditAdjustments.h>
|
|
#import <LegacyComponents/TGMediaVideoConverter.h>
|
|
#import "TGMediaPickerGallerySelectedItemsModel.h"
|
|
|
|
#import "TGModernGallerySelectableItem.h"
|
|
#import "TGModernGalleryEditableItem.h"
|
|
#import "TGMediaPickerGalleryPhotoItem.h"
|
|
#import "TGMediaPickerGalleryVideoItem.h"
|
|
#import "TGMediaPickerGalleryPhotoItemView.h"
|
|
#import "TGMediaPickerGalleryVideoItemView.h"
|
|
|
|
#import <LegacyComponents/TGMessageImageViewOverlayView.h>
|
|
|
|
#import <LegacyComponents/TGPhotoEditorTabController.h>
|
|
#import <LegacyComponents/TGPhotoToolbarView.h>
|
|
#import <LegacyComponents/TGPhotoEditorButton.h>
|
|
#import "TGCheckButtonView.h"
|
|
#import "TGMediaPickerPhotoCounterButton.h"
|
|
#import "TGMediaPickerPhotoStripView.h"
|
|
|
|
#import "TGMediaPickerScrubberHeaderView.h"
|
|
#import "TGPhotoEditorInterfaceAssets.h"
|
|
|
|
#import <LegacyComponents/TGMenuView.h>
|
|
#import <LegacyComponents/TGTooltipView.h>
|
|
|
|
#import <LegacyComponents/TGPhotoCaptionInputMixin.h>
|
|
|
|
@interface TGMediaPickerGalleryWrapperView: UIView
|
|
{
|
|
|
|
}
|
|
@end
|
|
|
|
@implementation TGMediaPickerGalleryWrapperView
|
|
|
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
|
|
__block UIView *result = nil;
|
|
[self.subviews enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(__kindof UIView * _Nonnull view, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
UIView *hitTestView = [view hitTest:[self convertPoint:point toView:view] withEvent:event];
|
|
if (hitTestView != nil) {
|
|
*stop = true;
|
|
result = hitTestView;
|
|
}
|
|
}];
|
|
return result;
|
|
}
|
|
|
|
@end
|
|
|
|
@interface TGMediaPickerGalleryInterfaceView () <ASWatcher>
|
|
{
|
|
id<TGModernGalleryItem> _currentItem;
|
|
__weak TGModernGalleryItemView *_currentItemView;
|
|
|
|
TGMediaSelectionContext *_selectionContext;
|
|
TGMediaEditingContext *_editingContext;
|
|
|
|
NSMutableArray *_itemHeaderViews;
|
|
NSMutableArray *_itemFooterViews;
|
|
|
|
UIView *_wrapperView;
|
|
UIView *_headerWrapperView;
|
|
TGPhotoToolbarView *_portraitToolbarView;
|
|
TGPhotoToolbarView *_landscapeToolbarView;
|
|
|
|
UIImageView *_arrowView;
|
|
UILabel *_recipientLabel;
|
|
|
|
TGPhotoCaptionInputMixin *_captionMixin;
|
|
|
|
TGModernButton *_muteButton;
|
|
TGModernButton *_telescopeButton;
|
|
TGCheckButtonView *_checkButton;
|
|
bool _ignoreSetSelected;
|
|
TGMediaPickerPhotoCounterButton *_photoCounterButton;
|
|
TGMediaPickerGroupButton *_groupButton;
|
|
TGMediaPickerCameraButton *_cameraButton;
|
|
|
|
TGMediaPickerPhotoStripView *_selectedPhotosView;
|
|
|
|
SMetaDisposable *_adjustmentsDisposable;
|
|
SMetaDisposable *_captionDisposable;
|
|
SMetaDisposable *_itemAvailabilityDisposable;
|
|
SMetaDisposable *_itemSelectedDisposable;
|
|
id<SDisposable> _selectionChangedDisposable;
|
|
id<SDisposable> _groupingChangedDisposable;
|
|
id<SDisposable> _timersChangedDisposable;
|
|
id<SDisposable> _adjustmentsChangedDisposable;
|
|
|
|
NSTimer *_tooltipTimer;
|
|
TGMenuContainerView *_tooltipContainerView;
|
|
|
|
SMetaDisposable *_tooltipDismissDisposable;
|
|
|
|
void (^_closePressed)();
|
|
void (^_scrollViewOffsetRequested)(CGFloat offset);
|
|
|
|
id<LegacyComponentsContext> _context;
|
|
|
|
bool _ignoreSelectionUpdates;
|
|
bool _canSendTelescope;
|
|
bool _canShowTelescope;
|
|
}
|
|
|
|
@property (nonatomic, strong) ASHandle *actionHandle;
|
|
@property (nonatomic, copy) UIViewController *(^controller)();
|
|
|
|
@end
|
|
|
|
@implementation TGMediaPickerGalleryInterfaceView
|
|
|
|
@synthesize safeAreaInset = _safeAreaInset;
|
|
|
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context focusItem:(id<TGModernGalleryItem>)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasSelectionPanel:(bool)hasSelectionPanel hasCameraButton:(bool)hasCameraButton recipientName:(NSString *)recipientName isScheduledMessages:(bool)isScheduledMessages canShowTelescope:(bool)canShowTelescope canSendTelescope:(bool)canSendTelescope
|
|
{
|
|
self = [super initWithFrame:CGRectZero];
|
|
if (self != nil)
|
|
{
|
|
[[LegacyComponentsGlobals provider] makeViewDisableInteractiveKeyboardGestureRecognizer:self];
|
|
|
|
_actionHandle = [[ASHandle alloc] initWithDelegate:self releaseOnMainThread:true];
|
|
|
|
_adjustmentsDisposable = [[SMetaDisposable alloc] init];
|
|
_captionDisposable = [[SMetaDisposable alloc] init];
|
|
_itemSelectedDisposable = [[SMetaDisposable alloc] init];
|
|
_itemAvailabilityDisposable = [[SMetaDisposable alloc] init];
|
|
_tooltipDismissDisposable = [[SMetaDisposable alloc] init];
|
|
|
|
_context = context;
|
|
_selectionContext = selectionContext;
|
|
_editingContext = editingContext;
|
|
|
|
_hasSwipeGesture = true;
|
|
|
|
_itemHeaderViews = [[NSMutableArray alloc] init];
|
|
_itemFooterViews = [[NSMutableArray alloc] init];
|
|
|
|
_wrapperView = [[TGMediaPickerGalleryWrapperView alloc] initWithFrame:CGRectZero];
|
|
[self addSubview:_wrapperView];
|
|
|
|
_headerWrapperView = [[UIView alloc] init];
|
|
[_wrapperView addSubview:_headerWrapperView];
|
|
|
|
__weak TGMediaPickerGalleryInterfaceView *weakSelf = self;
|
|
void(^toolbarCancelPressed)(void) = ^
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf != nil)
|
|
[strongSelf cancelButtonPressed];
|
|
};
|
|
void(^toolbarDonePressed)(void) = ^
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
strongSelf->_ignoreSelectionUpdates = true;
|
|
[strongSelf->_selectionChangedDisposable dispose];
|
|
[strongSelf->_itemSelectedDisposable dispose];
|
|
|
|
[strongSelf.window endEditing:true];
|
|
strongSelf->_portraitToolbarView.doneButton.userInteractionEnabled = false;
|
|
strongSelf->_landscapeToolbarView.doneButton.userInteractionEnabled = false;
|
|
|
|
if (strongSelf->_captionMixin.editing) {
|
|
[strongSelf->_captionMixin finishEditing];
|
|
TGDispatchAfter(0.1, dispatch_get_main_queue(), ^{
|
|
strongSelf->_donePressed(strongSelf->_currentItem);
|
|
});
|
|
} else {
|
|
strongSelf->_donePressed(strongSelf->_currentItem);
|
|
}
|
|
|
|
[strongSelf->_captionMixin onAnimateOut];
|
|
};
|
|
void(^toolbarDoneLongPressed)(id) = ^(id sender)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
[strongSelf.window endEditing:true];
|
|
if (strongSelf->_doneLongPressed != nil)
|
|
strongSelf->_doneLongPressed(strongSelf->_currentItem);
|
|
|
|
[[NSUserDefaults standardUserDefaults] setObject:@(3) forKey:@"TG_displayedMediaTimerTooltip_v3"];
|
|
};
|
|
|
|
_canSendTelescope = canSendTelescope;
|
|
_canShowTelescope = canShowTelescope;
|
|
|
|
_muteButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0, 0, 39.0f, 39.0f)];
|
|
_muteButton.hidden = true;
|
|
_muteButton.adjustsImageWhenHighlighted = false;
|
|
[_muteButton setBackgroundImage:[TGPhotoEditorInterfaceAssets gifBackgroundImage] forState:UIControlStateNormal];
|
|
[_muteButton setImage:[TGPhotoEditorInterfaceAssets muteIcon] forState:UIControlStateNormal];
|
|
[_muteButton setImage:[TGPhotoEditorInterfaceAssets muteActiveIcon] forState:UIControlStateSelected];
|
|
[_muteButton setImage:[TGPhotoEditorInterfaceAssets muteActiveIcon] forState:UIControlStateSelected | UIControlStateHighlighted];
|
|
[_muteButton addTarget:self action:@selector(toggleSendAsGif) forControlEvents:UIControlEventTouchUpInside];
|
|
[_wrapperView addSubview:_muteButton];
|
|
|
|
_telescopeButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0, 0, 39.0f, 39.0f)];
|
|
_telescopeButton.hidden = true;
|
|
_telescopeButton.adjustsImageWhenHighlighted = false;
|
|
[_telescopeButton setBackgroundImage:[TGPhotoEditorInterfaceAssets gifBackgroundImage] forState:UIControlStateNormal];
|
|
[_telescopeButton setImage:[TGPhotoEditorInterfaceAssets telescopeIcon] forState:UIControlStateNormal];
|
|
if (_canSendTelescope) {
|
|
[_telescopeButton setImage:[TGPhotoEditorInterfaceAssets telescopeActiveIcon] forState:UIControlStateSelected];
|
|
[_telescopeButton setImage:[TGPhotoEditorInterfaceAssets telescopeActiveIcon] forState:UIControlStateSelected | UIControlStateHighlighted];
|
|
[_telescopeButton setImage:[TGPhotoEditorInterfaceAssets telescopeActiveIcon] forState:UIControlStateSelected];
|
|
} else {
|
|
_telescopeButton.fadeDisabled = true;
|
|
}
|
|
[_telescopeButton addTarget:self action:@selector(toggleSendAsTelescope) forControlEvents:UIControlEventTouchUpInside];
|
|
[_wrapperView addSubview:_telescopeButton];
|
|
|
|
if (recipientName.length > 0)
|
|
{
|
|
_arrowView = [[UIImageView alloc] initWithImage: TGComponentsImageNamed(@"PhotoPickerArrow")];
|
|
_arrowView.alpha = 0.6f;
|
|
[_wrapperView addSubview:_arrowView];
|
|
|
|
_recipientLabel = [[UILabel alloc] init];
|
|
_recipientLabel.alpha = 0.6;
|
|
_recipientLabel.backgroundColor = [UIColor clearColor];
|
|
_recipientLabel.font = TGBoldSystemFontOfSize(13.0f);
|
|
_recipientLabel.textColor = UIColorRGB(0xffffff);
|
|
_recipientLabel.text = recipientName;
|
|
_recipientLabel.userInteractionEnabled = false;
|
|
[_recipientLabel sizeToFit];
|
|
[_wrapperView addSubview:_recipientLabel];
|
|
}
|
|
|
|
if (hasCameraButton)
|
|
{
|
|
_cameraButton = [[TGMediaPickerCameraButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 44.0f, 44.0f)];
|
|
_cameraButton.adjustsImageWhenHighlighted = false;
|
|
[_cameraButton addTarget:self action:@selector(cameraButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
[_wrapperView addSubview:_cameraButton];
|
|
|
|
//if (_selectionContext != nil)
|
|
// [_cameraButton setHidden:true animated:false];
|
|
}
|
|
|
|
if (_selectionContext != nil)
|
|
{
|
|
_checkButton = [[TGCheckButtonView alloc] initWithStyle:TGCheckButtonStyleGallery];
|
|
_checkButton.frame = CGRectMake(self.frame.size.width - 53, 11, _checkButton.frame.size.width, _checkButton.frame.size.height);
|
|
[_checkButton addTarget:self action:@selector(checkButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
|
[_wrapperView addSubview:_checkButton];
|
|
|
|
if (hasSelectionPanel)
|
|
{
|
|
_selectedPhotosView = [[TGMediaPickerPhotoStripView alloc] initWithFrame:CGRectZero];
|
|
_selectedPhotosView.selectionContext = _selectionContext;
|
|
_selectedPhotosView.editingContext = _editingContext;
|
|
_selectedPhotosView.itemSelected = ^(NSInteger index)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
if (strongSelf.photoStripItemSelected != nil)
|
|
strongSelf.photoStripItemSelected(index);
|
|
};
|
|
_selectedPhotosView.hidden = true;
|
|
[_wrapperView addSubview:_selectedPhotosView];
|
|
}
|
|
|
|
_photoCounterButton = [[TGMediaPickerPhotoCounterButton alloc] initWithFrame:CGRectMake(0, 0, 64, 38)];
|
|
[_photoCounterButton addTarget:self action:@selector(photoCounterButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
|
_photoCounterButton.userInteractionEnabled = false;
|
|
[_wrapperView addSubview:_photoCounterButton];
|
|
|
|
_selectionChangedDisposable = [[_selectionContext selectionChangedSignal] startStrictWithNext:^(id next)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
id<TGMediaSelectableItem> selectableItem = nil;
|
|
if ([strongSelf->_currentItem conformsToProtocol:@protocol(TGModernGallerySelectableItem)])
|
|
selectableItem = ((id<TGModernGallerySelectableItem>)strongSelf->_currentItem).selectableMediaItem;
|
|
|
|
if (selectableItem != nil)
|
|
[strongSelf->_checkButton setNumber:[strongSelf->_selectionContext indexOfItem:selectableItem]];
|
|
|
|
[strongSelf updateGroupingButtonVisibility];
|
|
} file:__FILE_NAME__ line:__LINE__];
|
|
|
|
if (_selectionContext.allowGrouping)
|
|
{
|
|
if (_editingContext != nil)
|
|
{
|
|
_timersChangedDisposable = [_editingContext.timersUpdatedSignal startStrictWithNext:^(__unused NSNumber *next)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
[strongSelf updateGroupingButtonVisibility];
|
|
} file:__FILE_NAME__ line:__LINE__];
|
|
|
|
_adjustmentsChangedDisposable = [_editingContext.adjustmentsUpdatedSignal startStrictWithNext:^(__unused NSNumber *next)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
[strongSelf updateGroupingButtonVisibility];
|
|
} file:__FILE_NAME__ line:__LINE__];
|
|
}
|
|
|
|
[self updateGroupingButtonVisibility];
|
|
}
|
|
}
|
|
|
|
[self updateEditorButtonsForItem:focusItem animated:false];
|
|
|
|
_captionMixin = [[TGPhotoCaptionInputMixin alloc] init];
|
|
_captionMixin.panelParentView = ^UIView *
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
return strongSelf->_wrapperView;
|
|
};
|
|
|
|
_captionMixin.panelFocused = ^
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
TGModernGalleryItemView *currentItemView = strongSelf->_currentItemView;
|
|
if ([currentItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]])
|
|
{
|
|
TGMediaPickerGalleryVideoItemView *videoItemView = (TGMediaPickerGalleryVideoItemView *)strongSelf->_currentItemView;
|
|
[videoItemView stop];
|
|
}
|
|
|
|
[strongSelf setSelectionInterfaceHidden:true animated:true];
|
|
[strongSelf setItemHeaderViewHidden:true animated:true];
|
|
};
|
|
|
|
_captionMixin.finishedWithCaption = ^(NSAttributedString *caption)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
TGModernGalleryItemView *currentItemView = strongSelf->_currentItemView;
|
|
if ([currentItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]])
|
|
{
|
|
TGMediaPickerGalleryVideoItemView *videoItemView = (TGMediaPickerGalleryVideoItemView *)strongSelf->_currentItemView;
|
|
[videoItemView returnFromEditing];
|
|
}
|
|
|
|
[strongSelf setSelectionInterfaceHidden:false delay:0.25 animated:true];
|
|
[strongSelf setItemHeaderViewHidden:false animated:true];
|
|
|
|
if (strongSelf.captionSet != nil)
|
|
strongSelf.captionSet(strongSelf->_currentItem, caption);
|
|
|
|
[strongSelf updateEditorButtonsForItem:strongSelf->_currentItem animated:false];
|
|
};
|
|
|
|
_captionMixin.keyboardHeightChanged = ^(CGFloat keyboardHeight, NSTimeInterval duration, NSInteger animationCurve)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
if (keyboardHeight > 0) {
|
|
[strongSelf->_portraitToolbarView setAllButtonsHidden:true animated:true];
|
|
} else {
|
|
[strongSelf->_portraitToolbarView setAllButtonsHidden:false animated:true];
|
|
}
|
|
|
|
CGFloat offset = 0.0f;
|
|
if (keyboardHeight > 0)
|
|
offset = -keyboardHeight / 2.0f;
|
|
|
|
[UIView animateWithDuration:duration delay:0.0f options:animationCurve animations:^
|
|
{
|
|
if (strongSelf->_scrollViewOffsetRequested != nil)
|
|
strongSelf->_scrollViewOffsetRequested(offset);
|
|
} completion:nil];
|
|
};
|
|
|
|
_captionMixin.timerUpdated = ^(NSNumber *timeout) {
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
if (![strongSelf->_currentItem conformsToProtocol:@protocol(TGModernGalleryEditableItem)])
|
|
return;
|
|
|
|
id<TGModernGalleryEditableItem> galleryEditableItem = (id<TGModernGalleryEditableItem>)strongSelf->_currentItem;
|
|
[strongSelf->_editingContext setTimer:timeout forItem:galleryEditableItem.editableMediaItem];
|
|
|
|
[strongSelf->_selectionContext setItem:(id<TGMediaSelectableItem>)galleryEditableItem.editableMediaItem selected:true animated:true sender:nil];
|
|
};
|
|
|
|
_captionMixin.captionIsAboveUpdated = ^(bool captionIsAbove) {
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
[strongSelf->_editingContext setCaptionAbove:captionIsAbove];
|
|
};
|
|
|
|
_captionMixin.stickersContext = stickersContext;
|
|
[_captionMixin createInputPanelIfNeeded];
|
|
|
|
TGPhotoEditorDoneButton doneButton = isScheduledMessages ? TGPhotoEditorDoneButtonSchedule : TGPhotoEditorDoneButtonSend;
|
|
|
|
_portraitToolbarView = [[TGPhotoToolbarView alloc] initWithContext:_context backButton:TGPhotoEditorBackButtonBack doneButton:doneButton solidBackground:false];
|
|
_portraitToolbarView.cancelPressed = toolbarCancelPressed;
|
|
_portraitToolbarView.donePressed = toolbarDonePressed;
|
|
_portraitToolbarView.doneLongPressed = toolbarDoneLongPressed;
|
|
[_wrapperView addSubview:_portraitToolbarView];
|
|
|
|
_landscapeToolbarView = [[TGPhotoToolbarView alloc] initWithContext:_context backButton:TGPhotoEditorBackButtonBack doneButton:doneButton solidBackground:false];
|
|
_landscapeToolbarView.cancelPressed = toolbarCancelPressed;
|
|
_landscapeToolbarView.donePressed = toolbarDonePressed;
|
|
_landscapeToolbarView.doneLongPressed = toolbarDoneLongPressed;
|
|
|
|
if ([UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPad)
|
|
[_wrapperView addSubview:_landscapeToolbarView];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
[_actionHandle reset];
|
|
|
|
[_adjustmentsDisposable dispose];
|
|
[_captionDisposable dispose];
|
|
[_itemSelectedDisposable dispose];
|
|
[_itemAvailabilityDisposable dispose];
|
|
[_selectionChangedDisposable dispose];
|
|
[_timersChangedDisposable dispose];
|
|
[_adjustmentsChangedDisposable dispose];
|
|
}
|
|
|
|
- (bool)updateGroupingButtonVisibility
|
|
{
|
|
bool onlyGroupableMedia = true;
|
|
for (id item in _selectionContext.selectedItems)
|
|
{
|
|
if ([item isKindOfClass:[TGMediaAsset class]])
|
|
{
|
|
if (((TGMediaAsset *)item).type == TGMediaAssetGifType)
|
|
{
|
|
onlyGroupableMedia = false;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if ([[_editingContext timerForItem:item] integerValue] > 0)
|
|
{
|
|
onlyGroupableMedia = false;
|
|
break;
|
|
}
|
|
|
|
id<TGMediaEditAdjustments> adjustments = [_editingContext adjustmentsForItem:item];
|
|
if ([adjustments isKindOfClass:[TGMediaVideoEditAdjustments class]] && (((TGMediaVideoEditAdjustments *)adjustments).sendAsGif || ((TGMediaVideoEditAdjustments *)adjustments).sendAsTelescope))
|
|
|
|
{
|
|
onlyGroupableMedia = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool groupingButtonVisible = _groupButton != nil && onlyGroupableMedia && _selectionContext.count > 1;
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
[_groupButton setInternalHidden:!groupingButtonVisible animated:true];
|
|
});
|
|
|
|
return groupingButtonVisible;
|
|
}
|
|
|
|
- (void)updateCameraButtonVisibility
|
|
{
|
|
|
|
}
|
|
|
|
- (void)setHasCaptions:(bool)hasCaptions
|
|
{
|
|
_hasCaptions = hasCaptions;
|
|
if (!hasCaptions)
|
|
[_captionMixin destroy];
|
|
}
|
|
|
|
- (void)setAllowCaptionEntities:(bool)allowCaptionEntities
|
|
{
|
|
_allowCaptionEntities = allowCaptionEntities;
|
|
_captionMixin.allowEntities = allowCaptionEntities;
|
|
}
|
|
|
|
- (void)setClosePressed:(void (^)())closePressed
|
|
{
|
|
_closePressed = [closePressed copy];
|
|
}
|
|
|
|
- (void)setScrollViewOffsetRequested:(void (^)(CGFloat))scrollViewOffsetRequested
|
|
{
|
|
_scrollViewOffsetRequested = [scrollViewOffsetRequested copy];
|
|
}
|
|
|
|
- (void)setEditorTabPressed:(void (^)(TGPhotoEditorTab tab))editorTabPressed
|
|
{
|
|
__weak TGMediaPickerGalleryInterfaceView *weakSelf = self;
|
|
void (^tabPressed)(TGPhotoEditorTab) = ^(TGPhotoEditorTab tab)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
[strongSelf tooltipTimerTick];
|
|
editorTabPressed(tab);
|
|
};
|
|
_portraitToolbarView.tabPressed = tabPressed;
|
|
_landscapeToolbarView.tabPressed = tabPressed;
|
|
}
|
|
|
|
- (void)openTimerSetup
|
|
{
|
|
if ([_currentItem conformsToProtocol:@protocol(TGModernGalleryEditableItem)])
|
|
{
|
|
if (self.timerRequested != nil)
|
|
self.timerRequested();
|
|
|
|
if (!TGIsPad())
|
|
[self setAllInterfaceHidden:true delay:0.0f animated:true];
|
|
}
|
|
}
|
|
|
|
- (UIView *)timerButton
|
|
{
|
|
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
|
|
return [_portraitToolbarView buttonForTab:TGPhotoEditorTimerTab];
|
|
else
|
|
return [_landscapeToolbarView buttonForTab:TGPhotoEditorTimerTab];
|
|
}
|
|
|
|
- (void)setSelectedItemsModel:(TGMediaPickerGallerySelectedItemsModel *)selectedItemsModel
|
|
{
|
|
_selectedPhotosView.selectedItemsModel = selectedItemsModel;
|
|
[_selectedPhotosView reloadData];
|
|
|
|
if (selectedItemsModel != nil && _selectedPhotosView != nil)
|
|
_photoCounterButton.userInteractionEnabled = true;
|
|
}
|
|
|
|
- (void)setUsesSimpleLayout:(bool)usesSimpleLayout
|
|
{
|
|
_usesSimpleLayout = usesSimpleLayout;
|
|
_landscapeToolbarView.hidden = usesSimpleLayout;
|
|
}
|
|
|
|
- (void)itemFocused:(id<TGModernGalleryItem>)item itemView:(TGModernGalleryItemView *)itemView
|
|
{
|
|
_currentItem = item;
|
|
_currentItemView = itemView;
|
|
|
|
[_currentItemView setSafeAreaInset:[self localSafeAreaInset]];
|
|
|
|
UIEdgeInsets screenEdges = [self screenEdges];
|
|
|
|
__weak TGMediaPickerGalleryInterfaceView *weakSelf = self;
|
|
|
|
[self _layoutRecipientLabelForOrientation:[self interfaceOrientation] screenEdges:screenEdges hasHeaderView:(itemView.headerView != nil)];
|
|
|
|
if (_selectionContext != nil)
|
|
{
|
|
_checkButton.frame = [self _checkButtonFrameForOrientation:[self interfaceOrientation] screenEdges:screenEdges hasHeaderView:(itemView.headerView != nil)];
|
|
_groupButton.frame = [self _groupButtonFrameForOrientation:[self interfaceOrientation] screenEdges:screenEdges hasHeaderView:(itemView.headerView != nil)];
|
|
|
|
SSignal *signal = nil;
|
|
id<TGMediaSelectableItem>selectableItem = nil;
|
|
if ([_currentItem conformsToProtocol:@protocol(TGModernGallerySelectableItem)])
|
|
selectableItem = ((id<TGModernGallerySelectableItem>)_currentItem).selectableMediaItem;
|
|
|
|
if (!_ignoreSetSelected) {
|
|
[_checkButton setSelected:[_selectionContext isItemSelected:selectableItem] animated:false];
|
|
}
|
|
[_checkButton setNumber:[_selectionContext indexOfItem:selectableItem]];
|
|
signal = [_selectionContext itemInformativeSelectedSignal:selectableItem];
|
|
[_itemSelectedDisposable setDisposable:[signal startStrictWithNext:^(TGMediaSelectionChange *next)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
if (next.sender != strongSelf->_checkButton)
|
|
[strongSelf->_checkButton setSelected:next.selected animated:next.animated];
|
|
} file:__FILE_NAME__ line:__LINE__]];
|
|
}
|
|
|
|
[self updateEditorButtonsForItem:item animated:true];
|
|
|
|
__weak TGModernGalleryItemView *weakItemView = itemView;
|
|
[_itemAvailabilityDisposable setDisposable:[[[itemView contentAvailabilityStateSignal] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id next)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
__strong TGModernGalleryItemView *strongItemView = weakItemView;
|
|
if (strongSelf == nil || strongItemView == nil)
|
|
return;
|
|
|
|
bool available = [next boolValue];
|
|
|
|
NSString *itemId = nil;
|
|
if ([strongItemView.item respondsToSelector:@selector(uniqueId)])
|
|
itemId = [itemView.item performSelector:@selector(uniqueId)];
|
|
|
|
NSString *currentId = nil;
|
|
if ([strongSelf->_currentItem respondsToSelector:@selector(uniqueId)])
|
|
currentId = [strongSelf->_currentItem performSelector:@selector(uniqueId)];
|
|
|
|
if (strongItemView.item == strongSelf->_currentItem || [itemId isEqualToString:currentId])
|
|
{
|
|
[strongSelf->_portraitToolbarView setEditButtonsEnabled:available animated:true];
|
|
[strongSelf->_landscapeToolbarView setEditButtonsEnabled:available animated:true];
|
|
|
|
bool sendableAsGif = !strongSelf->_inhibitMute && [strongItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]];
|
|
if ([strongSelf->_currentItem isKindOfClass:[TGMediaPickerGalleryVideoItem class]]) {
|
|
TGMediaPickerGalleryVideoItem *item = (TGMediaPickerGalleryVideoItem *)strongSelf->_currentItem;
|
|
if ([item.asset isKindOfClass:[TGCameraCapturedVideo class]] && ((TGCameraCapturedVideo *)item.asset).isAnimation) {
|
|
sendableAsGif = false;
|
|
}
|
|
}
|
|
strongSelf->_muteButton.hidden = !sendableAsGif;
|
|
if (strongSelf->_canShowTelescope) {
|
|
strongSelf->_telescopeButton.hidden = !sendableAsGif;
|
|
}
|
|
}
|
|
} file:__FILE_NAME__ line:__LINE__]];
|
|
|
|
UIImage *muteIcon = [TGPhotoEditorInterfaceAssets muteIcon];
|
|
UIImage *muteActiveIcon = [TGPhotoEditorInterfaceAssets muteActiveIcon];
|
|
if ([item isKindOfClass:[TGMediaPickerGalleryVideoItem class]]) {
|
|
TGMediaPickerGalleryVideoItem *videoGalleryItem = (TGMediaPickerGalleryVideoItem *)item;
|
|
if ([videoGalleryItem.editableMediaItem isKindOfClass:[TGMediaAsset class]]) {
|
|
TGMediaAsset *asset = (TGMediaAsset *)videoGalleryItem.editableMediaItem;
|
|
if (asset.type == TGMediaAssetPhotoType) {
|
|
muteIcon = [TGPhotoEditorInterfaceAssets gifIcon];
|
|
muteActiveIcon = [TGPhotoEditorInterfaceAssets gifActiveIcon];
|
|
}
|
|
}
|
|
}
|
|
[_muteButton setImage:muteIcon forState:UIControlStateNormal];
|
|
[_muteButton setImage:muteActiveIcon forState:UIControlStateSelected];
|
|
[_muteButton setImage:muteActiveIcon forState:UIControlStateSelected | UIControlStateHighlighted];
|
|
|
|
[self setNeedsLayout];
|
|
}
|
|
|
|
- (TGPhotoEditorTab)currentTabs
|
|
{
|
|
return _portraitToolbarView.currentTabs;
|
|
}
|
|
|
|
- (void)setTabBarUserInteractionEnabled:(bool)enabled
|
|
{
|
|
_portraitToolbarView.userInteractionEnabled = enabled;
|
|
_landscapeToolbarView.userInteractionEnabled = enabled;
|
|
}
|
|
|
|
- (void)setThumbnailSignalForItem:(SSignal *(^)(id))thumbnailSignalForItem
|
|
{
|
|
[_selectedPhotosView setThumbnailSignalForItem:thumbnailSignalForItem];
|
|
}
|
|
|
|
- (void)cancelButtonPressed
|
|
{
|
|
_ignoreSelectionUpdates = true;
|
|
if (_cameraButton != nil && _selectionContext != nil)
|
|
{
|
|
__weak TGMediaPickerGalleryInterfaceView *weakSelf = self;
|
|
|
|
TGMenuSheetController *controller = [[TGMenuSheetController alloc] initWithContext:_context dark:false];
|
|
controller.dismissesByOutsideTap = true;
|
|
controller.narrowInLandscape = true;
|
|
__weak TGMenuSheetController *weakController = controller;
|
|
|
|
NSArray *items = @
|
|
[
|
|
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Camera.Discard") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
|
{
|
|
__strong TGMenuSheetController *strongController = weakController;
|
|
if (strongController == nil)
|
|
return;
|
|
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
strongSelf->_capturing = false;
|
|
strongSelf->_closePressed();
|
|
|
|
[strongController dismissAnimated:true manual:false completion:nil];
|
|
}],
|
|
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
|
{
|
|
__strong TGMenuSheetController *strongController = weakController;
|
|
if (strongController != nil)
|
|
[strongController dismissAnimated:true];
|
|
}]
|
|
];
|
|
|
|
[controller setItemViews:items];
|
|
controller.sourceRect = ^
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return CGRectZero;
|
|
|
|
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
|
|
return [strongSelf convertRect:strongSelf->_portraitToolbarView.cancelButtonFrame fromView:strongSelf->_portraitToolbarView];
|
|
else
|
|
return [strongSelf convertRect:strongSelf->_landscapeToolbarView.cancelButtonFrame fromView:strongSelf->_landscapeToolbarView];
|
|
};
|
|
[controller presentInViewController:self.controller() sourceView:self animated:true];
|
|
}
|
|
else
|
|
{
|
|
_capturing = false;
|
|
_closePressed();
|
|
}
|
|
}
|
|
|
|
- (void)cameraButtonPressed
|
|
{
|
|
_capturing = true;
|
|
_closePressed();
|
|
}
|
|
|
|
- (void)checkButtonPressed
|
|
{
|
|
if (_currentItem == nil)
|
|
return;
|
|
|
|
bool animated = false;
|
|
if (!_selectedPhotosView.isAnimating)
|
|
animated = true;
|
|
|
|
id<TGMediaSelectableItem>selectableItem = nil;
|
|
if ([_currentItem conformsToProtocol:@protocol(TGModernGallerySelectableItem)])
|
|
selectableItem = ((id<TGModernGallerySelectableItem>)_currentItem).selectableMediaItem;
|
|
|
|
_ignoreSetSelected = true;
|
|
|
|
if (selectableItem != nil) {
|
|
[_selectionContext setItem:selectableItem selected:!_checkButton.selected animated:animated sender:_checkButton];
|
|
bool value = [_selectionContext isItemSelected:selectableItem];
|
|
[_checkButton setSelected:value animated:true];
|
|
} else {
|
|
[_checkButton setSelected:!_checkButton.selected animated:true];
|
|
}
|
|
|
|
_ignoreSetSelected = false;
|
|
}
|
|
|
|
- (void)photoCounterButtonPressed
|
|
{
|
|
bool selected = !_photoCounterButton.selected;
|
|
[_photoCounterButton setSelected:!_photoCounterButton.selected animated:true];
|
|
[_selectedPhotosView setHidden:!_photoCounterButton.selected animated:true];
|
|
[_groupButton setHidden:!_photoCounterButton.selected animated:true];
|
|
|
|
void (^changeBlock)(void) = ^
|
|
{
|
|
_cameraButton.frame = [self _cameraButtonFrameForOrientation:[self interfaceOrientation] screenEdges:[self screenEdges] hasHeaderView:(_currentItemView.headerView != nil) panelVisible:selected];
|
|
};
|
|
if (selected)
|
|
[UIView animateWithDuration:0.45 delay:0.0 usingSpringWithDamping:0.8f initialSpringVelocity:0.1 options:kNilOptions animations:changeBlock completion:nil];
|
|
else
|
|
[UIView animateWithDuration:0.3 delay:0.0 options:7 << 16 animations:changeBlock completion:nil];
|
|
|
|
[self updateGroupingButtonVisibility];
|
|
}
|
|
|
|
- (void)updateEditorButtonsForItem:(id<TGModernGalleryItem>)item animated:(bool)animated
|
|
{
|
|
__weak TGMediaPickerGalleryInterfaceView *weakSelf = self;
|
|
id<TGModernGalleryEditableItem> galleryEditableItem = (id<TGModernGalleryEditableItem>)item;
|
|
if ([item conformsToProtocol:@protocol(TGModernGalleryEditableItem)])
|
|
{
|
|
id<TGMediaEditableItem> editableMediaItem = [galleryEditableItem editableMediaItem];
|
|
[_captionDisposable setDisposable:[[galleryEditableItem.editingContext captionSignalForItem:editableMediaItem] startStrictWithNext:^(NSAttributedString *caption)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
[strongSelf->_captionMixin setCaption:caption animated:animated];
|
|
} file:__FILE_NAME__ line:__LINE__]];
|
|
}
|
|
|
|
if (_editingContext == nil || _editingContext.inhibitEditing)
|
|
{
|
|
[_portraitToolbarView setEditButtonsHidden:true animated:false];
|
|
[_landscapeToolbarView setEditButtonsHidden:true animated:false];
|
|
return;
|
|
}
|
|
|
|
TGPhotoEditorTab tabs = TGPhotoEditorNoneTab;
|
|
if ([item conformsToProtocol:@protocol(TGModernGalleryEditableItem)])
|
|
tabs = [(id<TGModernGalleryEditableItem>)item toolbarTabs];
|
|
|
|
if (iosMajorVersion() < 7 || self.onlyCrop)
|
|
{
|
|
tabs &= ~ TGPhotoEditorPaintTab;
|
|
tabs &= ~ TGPhotoEditorToolsTab;
|
|
}
|
|
|
|
if (iosMajorVersion() < 8)
|
|
tabs &= ~ TGPhotoEditorQualityTab;
|
|
|
|
if (!self.hasTimer)
|
|
tabs &= ~ TGPhotoEditorTimerTab;
|
|
|
|
[_portraitToolbarView setToolbarTabs:tabs animated:animated];
|
|
[_landscapeToolbarView setToolbarTabs:tabs animated:animated];
|
|
|
|
bool editButtonsHidden = ![item conformsToProtocol:@protocol(TGModernGalleryEditableItem)];
|
|
[_portraitToolbarView setEditButtonsHidden:editButtonsHidden animated:animated];
|
|
[_landscapeToolbarView setEditButtonsHidden:editButtonsHidden animated:animated];
|
|
|
|
if (editButtonsHidden)
|
|
{
|
|
[_adjustmentsDisposable setDisposable:nil];
|
|
[_captionDisposable setDisposable:nil];
|
|
return;
|
|
}
|
|
|
|
if ([item conformsToProtocol:@protocol(TGModernGalleryEditableItem)])
|
|
{
|
|
id<TGMediaEditableItem> editableMediaItem = [galleryEditableItem editableMediaItem];
|
|
|
|
bool isCaptionAbove = galleryEditableItem.editingContext.isCaptionAbove;
|
|
|
|
__weak id<TGModernGalleryEditableItem> weakGalleryEditableItem = galleryEditableItem;
|
|
[_adjustmentsDisposable setDisposable:[[[[galleryEditableItem.editingContext adjustmentsSignalForItem:editableMediaItem] mapToSignal:^SSignal *(id<TGMediaEditAdjustments> adjustments) {
|
|
__strong id<TGModernGalleryEditableItem> strongGalleryEditableItem = weakGalleryEditableItem;
|
|
if (strongGalleryEditableItem != nil) {
|
|
return [[strongGalleryEditableItem.editingContext timerSignalForItem:editableMediaItem] map:^id(id timer) {
|
|
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
|
if (adjustments != nil)
|
|
dict[@"adjustments"] = adjustments;
|
|
if (timer != nil)
|
|
dict[@"timer"] = timer;
|
|
return dict;
|
|
}];
|
|
} else {
|
|
return [SSignal never];
|
|
}
|
|
}] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSDictionary *dict)
|
|
{
|
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
id<TGMediaEditAdjustments> adjustments = dict[@"adjustments"];
|
|
NSNumber *timer = dict[@"timer"];
|
|
|
|
[strongSelf->_captionMixin setTimeout:[timer intValue] isVideo:editableMediaItem.isVideo isCaptionAbove:isCaptionAbove];
|
|
|
|
if ([adjustments isKindOfClass:[TGVideoEditAdjustments class]])
|
|
{
|
|
TGVideoEditAdjustments *videoAdjustments = (TGVideoEditAdjustments *)adjustments;
|
|
[strongSelf->_captionMixin setCaptionPanelHidden:(videoAdjustments.sendAsGif && strongSelf->_inhibitDocumentCaptions) animated:true];
|
|
}
|
|
else
|
|
{
|
|
[strongSelf->_captionMixin setCaptionPanelHidden:false animated:true];
|
|
}
|
|
|
|
CGSize originalSize = CGSizeZero;
|
|
if ([editableMediaItem respondsToSelector:@selector(originalSize)])
|
|
originalSize = editableMediaItem.originalSize;
|
|
|
|
[strongSelf updateEditorButtonsForAdjustments:adjustments dimensions:originalSize timer:timer];
|
|
} file:__FILE_NAME__ line:__LINE__]];
|
|
}
|
|
else
|
|
{
|
|
[_adjustmentsDisposable setDisposable:nil];
|
|
[_captionDisposable setDisposable:nil];
|
|
[self updateEditorButtonsForAdjustments:nil dimensions:CGSizeZero timer:nil];
|
|
[_captionMixin setCaption:nil animated:animated];
|
|
}
|
|
}
|
|
|
|
- (void)updateEditorButtonsForAdjustments:(id<TGMediaEditAdjustments>)adjustments dimensions:(CGSize)dimensions timer:(NSNumber *)timer
|
|
{
|
|
TGPhotoEditorTab highlightedButtons = [TGPhotoEditorTabController highlightedButtonsForEditorValues:adjustments forAvatar:false];
|
|
if (self.onlyCrop)
|
|
{
|
|
PGPhotoEditorValues *values = (PGPhotoEditorValues *)adjustments;
|
|
CGFloat height = values.originalSize.width * 0.704f;
|
|
CGFloat origin = floor((values.originalSize.height - height) / 2.0f);
|
|
if (fabs(values.cropRect.size.width - values.originalSize.width) < FLT_EPSILON && fabs(values.cropRect.size.height - height) < FLT_EPSILON && fabs(values.cropRect.origin.y - origin) < FLT_EPSILON)
|
|
{
|
|
highlightedButtons &= ~ TGPhotoEditorCropTab;
|
|
}
|
|
}
|
|
|
|
TGPhotoEditorTab disabledButtons = TGPhotoEditorNoneTab;
|
|
|
|
_muteButton.selected = adjustments.sendAsGif;
|
|
_telescopeButton.selected = adjustments.sendAsTelescope;
|
|
|
|
TGPhotoEditorButton *qualityButton = [_portraitToolbarView buttonForTab:TGPhotoEditorQualityTab];
|
|
if (qualityButton != nil)
|
|
{
|
|
TGMediaVideoConversionPreset preset = 0;
|
|
TGMediaVideoConversionPreset adjustmentsPreset = TGMediaVideoConversionPresetCompressedDefault;
|
|
if ([adjustments isKindOfClass:[TGMediaVideoEditAdjustments class]])
|
|
adjustmentsPreset = ((TGMediaVideoEditAdjustments *)adjustments).preset;
|
|
|
|
if (adjustmentsPreset != TGMediaVideoConversionPresetCompressedDefault)
|
|
{
|
|
preset = adjustmentsPreset;
|
|
}
|
|
else
|
|
{
|
|
NSNumber *presetValue = [[NSUserDefaults standardUserDefaults] objectForKey:@"TG_preferredVideoPreset_v0"];
|
|
if (presetValue != nil)
|
|
preset = (TGMediaVideoConversionPreset)[presetValue integerValue];
|
|
else
|
|
preset = TGMediaVideoConversionPresetCompressedMedium;
|
|
}
|
|
|
|
TGMediaVideoConversionPreset bestPreset = [TGMediaVideoConverter bestAvailablePresetForDimensions:dimensions];
|
|
if (preset > bestPreset)
|
|
preset = bestPreset;
|
|
|
|
UIImage *icon = [TGPhotoEditorInterfaceAssets qualityIconForPreset:preset];
|
|
qualityButton.iconImage = icon;
|
|
|
|
qualityButton = [_landscapeToolbarView buttonForTab:TGPhotoEditorQualityTab];
|
|
qualityButton.iconImage = icon;
|
|
}
|
|
|
|
bool willShowTimerTooltip = false;
|
|
TGPhotoEditorButton *timerButton = [_portraitToolbarView buttonForTab:TGPhotoEditorTimerTab];
|
|
if (timerButton != nil)
|
|
{
|
|
NSInteger value = [timer integerValue];
|
|
|
|
UIImage *defaultIcon = [TGPhotoEditorInterfaceAssets timerIconForValue:0];
|
|
UIImage *icon = [TGPhotoEditorInterfaceAssets timerIconForValue:value];
|
|
[timerButton setIconImage:defaultIcon activeIconImage:icon];
|
|
|
|
TGPhotoEditorButton *landscapeTimerButton = [_landscapeToolbarView buttonForTab:TGPhotoEditorTimerTab];
|
|
|
|
timerButton = landscapeTimerButton;
|
|
[timerButton setIconImage:defaultIcon activeIconImage:icon];
|
|
|
|
if (value > 0)
|
|
highlightedButtons |= TGPhotoEditorTimerTab;
|
|
}
|
|
|
|
if ([self shouldDisplayTooltip])
|
|
{
|
|
willShowTimerTooltip = true;
|
|
TGDispatchAfter(0.5, dispatch_get_main_queue(), ^
|
|
{
|
|
if (!TGIsPad() && self.frame.size.width > self.frame.size.height)
|
|
[self setupTooltip:[_landscapeToolbarView convertRect:[_landscapeToolbarView doneButtonFrame] toView:self]];
|
|
else
|
|
[self setupTooltip:[_portraitToolbarView convertRect:[_portraitToolbarView doneButtonFrame] toView:self]];
|
|
});
|
|
}
|
|
|
|
if (adjustments.sendAsGif || adjustments.sendAsTelescope)
|
|
disabledButtons |= TGPhotoEditorQualityTab;
|
|
|
|
[_portraitToolbarView setEditButtonsHighlighted:highlightedButtons];
|
|
[_landscapeToolbarView setEditButtonsHighlighted:highlightedButtons];
|
|
|
|
[_portraitToolbarView setEditButtonsDisabled:disabledButtons];
|
|
[_landscapeToolbarView setEditButtonsDisabled:disabledButtons];
|
|
}
|
|
|
|
#pragma mark - Timer Tooltip
|
|
|
|
- (bool)shouldDisplayTooltip
|
|
{
|
|
return [[[NSUserDefaults standardUserDefaults] objectForKey:@"TG_displayedMediaTimerTooltip_v3"] intValue] < 3;
|
|
}
|
|
|
|
- (void)setupTooltip:(CGRect)rect
|
|
{
|
|
if (_tooltipContainerView != nil || !_hasTimer)
|
|
return;
|
|
|
|
_tooltipTimer = [TGTimerTarget scheduledMainThreadTimerWithTarget:self action:@selector(tooltipTimerTick) interval:3.5 repeat:false];
|
|
|
|
_tooltipContainerView = [[TGMenuContainerView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.frame.size.width, self.frame.size.height)];
|
|
[self addSubview:_tooltipContainerView];
|
|
|
|
NSMutableArray *actions = [[NSMutableArray alloc] init];
|
|
[actions addObject:[[NSDictionary alloc] initWithObjectsAndKeys:TGLocalized(@"Media.SendingOptionsTooltip"), @"title", nil]];
|
|
|
|
_tooltipContainerView.menuView.multiline = true;
|
|
[_tooltipContainerView.menuView setButtonsAndActions:actions watcherHandle:_actionHandle];
|
|
[_tooltipContainerView.menuView sizeToFit];
|
|
_tooltipContainerView.menuView.buttonHighlightDisabled = true;
|
|
|
|
[_tooltipContainerView showMenuFromRect:rect animated:false];
|
|
|
|
int counter = [[[NSUserDefaults standardUserDefaults] objectForKey:@"TG_displayedMediaTimerTooltip_v3"] intValue];
|
|
[[NSUserDefaults standardUserDefaults] setObject:@(counter + 1) forKey:@"TG_displayedMediaTimerTooltip_v3"];
|
|
}
|
|
|
|
- (void)tooltipTimerTick
|
|
{
|
|
[_tooltipTimer invalidate];
|
|
_tooltipTimer = nil;
|
|
|
|
[_tooltipContainerView hideMenu];
|
|
}
|
|
|
|
#pragma mark - Grouping Tooltip
|
|
|
|
- (void)actionStageActionRequested:(NSString *)action options:(id)__unused options
|
|
{
|
|
if ([action isEqualToString:@"menuAction"])
|
|
{
|
|
[_tooltipTimer invalidate];
|
|
_tooltipTimer = nil;
|
|
|
|
[_tooltipContainerView hideMenu];
|
|
}
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (void)updateSelectionInterface:(NSUInteger)selectedCount counterVisible:(bool)counterVisible animated:(bool)animated
|
|
{
|
|
if (_ignoreSelectionUpdates)
|
|
return;
|
|
|
|
if (counterVisible)
|
|
{
|
|
bool animateCount = animated && !(counterVisible && _photoCounterButton.internalHidden);
|
|
if (!animateCount && !_photoCounterButton.selected && !_photoCounterButton.internalHidden)
|
|
animateCount = true;
|
|
[_photoCounterButton setSelectedCount:selectedCount animated:animateCount];
|
|
[_photoCounterButton setInternalHidden:false animated:animated completion:nil];
|
|
}
|
|
else
|
|
{
|
|
bool animate = animated || (selectedCount == 0 && !counterVisible);
|
|
__weak TGMediaPickerPhotoCounterButton *weakButton = _photoCounterButton;
|
|
[_photoCounterButton setInternalHidden:true animated:animate completion:^
|
|
{
|
|
__strong TGMediaPickerPhotoCounterButton *strongButton = weakButton;
|
|
if (strongButton != nil)
|
|
{
|
|
strongButton.selected = false;
|
|
[strongButton setSelectedCount:selectedCount animated:false];
|
|
}
|
|
}];
|
|
[_selectedPhotosView setHidden:true animated:animated];
|
|
}
|
|
}
|
|
|
|
- (void)updateSelectedPhotosView:(bool)reload incremental:(bool)incremental add:(bool)add index:(NSInteger)index
|
|
{
|
|
if (_selectedPhotosView == nil)
|
|
return;
|
|
|
|
if (!reload)
|
|
return;
|
|
|
|
if (incremental)
|
|
{
|
|
if (add)
|
|
[_selectedPhotosView insertItemAtIndex:index];
|
|
else
|
|
[_selectedPhotosView deleteItemAtIndex:index];
|
|
}
|
|
else
|
|
{
|
|
[_selectedPhotosView reloadData];
|
|
}
|
|
}
|
|
|
|
- (void)setSelectionInterfaceHidden:(bool)hidden animated:(bool)animated
|
|
{
|
|
[self setSelectionInterfaceHidden:hidden delay:0.0 animated:animated];
|
|
}
|
|
|
|
- (void)setSelectionInterfaceHidden:(bool)hidden delay:(NSTimeInterval)__unused delay animated:(bool)animated
|
|
{
|
|
CGFloat alpha = (hidden ? 0.0f : 1.0f);
|
|
if (animated)
|
|
{
|
|
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionBeginFromCurrentState animations:^
|
|
{
|
|
_checkButton.alpha = alpha;
|
|
_muteButton.alpha = alpha;
|
|
_telescopeButton.alpha = alpha;
|
|
_arrowView.alpha = alpha * 0.6f;
|
|
_recipientLabel.alpha = alpha * 0.6;
|
|
} completion:^(BOOL finished)
|
|
{
|
|
if (finished)
|
|
{
|
|
_checkButton.userInteractionEnabled = !hidden;
|
|
_muteButton.userInteractionEnabled = !hidden;
|
|
_telescopeButton.userInteractionEnabled = !hidden;
|
|
}
|
|
}];
|
|
|
|
[UIView animateWithDuration:0.2 delay:delay options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionBeginFromCurrentState animations:^
|
|
{
|
|
_cameraButton.alpha = alpha;
|
|
} completion:^(BOOL finished)
|
|
{
|
|
if (finished)
|
|
_cameraButton.userInteractionEnabled = !hidden;
|
|
}];
|
|
}
|
|
else
|
|
{
|
|
_cameraButton.alpha = alpha;
|
|
_cameraButton.userInteractionEnabled = !hidden;
|
|
|
|
_checkButton.alpha = alpha;
|
|
_checkButton.userInteractionEnabled = !hidden;
|
|
|
|
_muteButton.alpha = alpha;
|
|
_muteButton.userInteractionEnabled = !hidden;
|
|
|
|
_telescopeButton.alpha = alpha;
|
|
_telescopeButton.userInteractionEnabled = !hidden;
|
|
|
|
_arrowView.alpha = alpha * 0.6f;
|
|
_recipientLabel.alpha = alpha * 0.6;
|
|
}
|
|
|
|
if (hidden)
|
|
{
|
|
[_photoCounterButton setSelected:false animated:animated];
|
|
[_selectedPhotosView setHidden:true animated:animated];
|
|
}
|
|
|
|
[_photoCounterButton setHidden:hidden delay:delay animated:animated];
|
|
|
|
if (!_groupButton.hidden)
|
|
[_groupButton setHidden:true animated:animated];
|
|
}
|
|
|
|
- (void)setAllInterfaceHidden:(bool)hidden delay:(NSTimeInterval)__unused delay animated:(bool)animated
|
|
{
|
|
CGFloat alpha = (hidden ? 0.0f : 1.0f);
|
|
if (animated)
|
|
{
|
|
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionBeginFromCurrentState animations:^
|
|
{
|
|
_checkButton.alpha = alpha;
|
|
_muteButton.alpha = alpha;
|
|
_telescopeButton.alpha = alpha;
|
|
_arrowView.alpha = alpha * 0.6;
|
|
_recipientLabel.alpha = alpha;
|
|
_portraitToolbarView.alpha = alpha;
|
|
_landscapeToolbarView.alpha = alpha;
|
|
_captionMixin.inputPanelView.alpha = alpha;
|
|
_captionMixin.backgroundView.alpha = alpha;
|
|
} completion:^(BOOL finished)
|
|
{
|
|
if (finished)
|
|
{
|
|
_checkButton.userInteractionEnabled = !hidden;
|
|
_muteButton.userInteractionEnabled = !hidden;
|
|
_telescopeButton.userInteractionEnabled = !hidden;
|
|
_portraitToolbarView.userInteractionEnabled = !hidden;
|
|
_landscapeToolbarView.userInteractionEnabled = !hidden;
|
|
_captionMixin.inputPanelView.userInteractionEnabled = !hidden;
|
|
_captionMixin.backgroundView.userInteractionEnabled = !hidden;
|
|
}
|
|
}];
|
|
|
|
[UIView animateWithDuration:0.2 delay:delay options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionBeginFromCurrentState animations:^
|
|
{
|
|
_cameraButton.alpha = alpha;
|
|
} completion:^(BOOL finished)
|
|
{
|
|
if (finished)
|
|
_cameraButton.userInteractionEnabled = !hidden;
|
|
}];
|
|
}
|
|
else
|
|
{
|
|
_cameraButton.alpha = alpha;
|
|
_cameraButton.userInteractionEnabled = !hidden;
|
|
|
|
_checkButton.alpha = alpha;
|
|
_checkButton.userInteractionEnabled = !hidden;
|
|
|
|
_muteButton.alpha = alpha;
|
|
_muteButton.userInteractionEnabled = !hidden;
|
|
|
|
_telescopeButton.alpha = alpha;
|
|
_telescopeButton.userInteractionEnabled = !hidden;
|
|
|
|
_arrowView.alpha = alpha * 0.6;
|
|
_recipientLabel.alpha = alpha;
|
|
|
|
_portraitToolbarView.alpha = alpha;
|
|
_portraitToolbarView.userInteractionEnabled = !hidden;
|
|
|
|
_landscapeToolbarView.alpha = alpha;
|
|
_landscapeToolbarView.userInteractionEnabled = !hidden;
|
|
|
|
_captionMixin.inputPanelView.alpha = alpha;
|
|
_captionMixin.inputPanelView.userInteractionEnabled = !hidden;
|
|
|
|
_captionMixin.backgroundView.alpha = alpha;
|
|
_captionMixin.backgroundView.userInteractionEnabled = !hidden;
|
|
}
|
|
|
|
if (hidden)
|
|
{
|
|
[_photoCounterButton setSelected:false animated:animated];
|
|
[_selectedPhotosView setHidden:true animated:animated];
|
|
}
|
|
|
|
[_photoCounterButton setHidden:hidden delay:delay animated:animated];
|
|
if (!_groupButton.hidden)
|
|
[_groupButton setHidden:true animated:animated];
|
|
|
|
[self setItemHeaderViewHidden:hidden animated:animated];
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (void)setItemHeaderViewHidden:(bool)hidden animated:(bool)animated
|
|
{
|
|
if (animated)
|
|
{
|
|
[UIView animateWithDuration:0.2f animations:^
|
|
{
|
|
for (UIView *view in _itemHeaderViews)
|
|
{
|
|
if (!view.hidden)
|
|
view.alpha = hidden ? 0.0f : 1.0f;
|
|
}
|
|
} completion:^(BOOL finished)
|
|
{
|
|
if (finished)
|
|
{
|
|
for (UIView *view in _itemHeaderViews)
|
|
{
|
|
if (!view.hidden)
|
|
view.userInteractionEnabled = !hidden;
|
|
}
|
|
}
|
|
}];
|
|
}
|
|
else
|
|
{
|
|
for (UIView *view in _itemHeaderViews)
|
|
{
|
|
if (!view.hidden)
|
|
{
|
|
view.alpha = hidden ? 0.0f : 1.0f;
|
|
view.userInteractionEnabled = !hidden;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)toggleSendAsGif
|
|
{
|
|
if (![_currentItem conformsToProtocol:@protocol(TGModernGalleryEditableItem)])
|
|
return;
|
|
|
|
TGModernGalleryItemView *currentItemView = _currentItemView;
|
|
bool sendableAsGif = [currentItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]];
|
|
if (sendableAsGif)
|
|
[(TGMediaPickerGalleryVideoItemView *)currentItemView toggleSendAsGif];
|
|
}
|
|
|
|
- (void)toggleSendAsTelescope
|
|
{
|
|
if (![_currentItem conformsToProtocol:@protocol(TGModernGalleryEditableItem)])
|
|
return;
|
|
|
|
TGModernGalleryItemView *currentItemView = _currentItemView;
|
|
bool sendableAsTelescope = [currentItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]];
|
|
if (sendableAsTelescope)
|
|
[(TGMediaPickerGalleryVideoItemView *)currentItemView toggleSendAsTelescope:_canSendTelescope dismissParent:^{
|
|
[self cancelButtonPressed];
|
|
}];
|
|
}
|
|
|
|
- (void)toggleGrouping
|
|
{
|
|
[_selectionContext toggleGrouping];
|
|
}
|
|
|
|
- (CGRect)itemFooterViewFrameForSize:(CGSize)size
|
|
{
|
|
CGFloat padding = TGPhotoEditorToolbarSize;
|
|
return CGRectMake(padding, 0.0f, size.width - padding * 2.0f, TGPhotoEditorToolbarSize);
|
|
}
|
|
|
|
- (void)addItemHeaderView:(UIView *)itemHeaderView
|
|
{
|
|
if (itemHeaderView == nil)
|
|
return;
|
|
|
|
[_itemHeaderViews addObject:itemHeaderView];
|
|
[_headerWrapperView addSubview:itemHeaderView];
|
|
itemHeaderView.frame = _headerWrapperView.bounds;
|
|
}
|
|
|
|
- (void)removeItemHeaderView:(UIView *)itemHeaderView
|
|
{
|
|
if (itemHeaderView == nil)
|
|
return;
|
|
|
|
[itemHeaderView removeFromSuperview];
|
|
[_itemHeaderViews removeObject:itemHeaderView];
|
|
}
|
|
|
|
- (void)addItemFooterView:(UIView *)itemFooterView
|
|
{
|
|
if (itemFooterView == nil)
|
|
return;
|
|
|
|
[_itemFooterViews addObject:itemFooterView];
|
|
[_portraitToolbarView addSubview:itemFooterView];
|
|
itemFooterView.frame = [self itemFooterViewFrameForSize:self.frame.size];
|
|
}
|
|
|
|
- (void)removeItemFooterView:(UIView *)itemFooterView
|
|
{
|
|
if (itemFooterView == nil)
|
|
return;
|
|
|
|
[itemFooterView removeFromSuperview];
|
|
[_itemFooterViews removeObject:itemFooterView];
|
|
}
|
|
|
|
- (void)addItemLeftAcessoryView:(UIView *)__unused itemLeftAcessoryView
|
|
{
|
|
|
|
}
|
|
|
|
- (void)removeItemLeftAcessoryView:(UIView *)__unused itemLeftAcessoryView
|
|
{
|
|
|
|
}
|
|
|
|
- (void)addItemRightAcessoryView:(UIView *)__unused itemRightAcessoryView
|
|
{
|
|
|
|
}
|
|
|
|
- (void)removeItemRightAcessoryView:(UIView *)__unused itemRightAcessoryView
|
|
{
|
|
|
|
}
|
|
|
|
- (void)animateTransitionInWithDuration:(NSTimeInterval)__unused dutation
|
|
{
|
|
|
|
}
|
|
|
|
- (void)animateTransitionOutWithDuration:(NSTimeInterval)__unused duration
|
|
{
|
|
[_captionMixin onAnimateOut];
|
|
}
|
|
|
|
- (void)onDismiss {
|
|
[_captionMixin onAnimateOut];
|
|
}
|
|
|
|
- (void)setTransitionOutProgress:(CGFloat)transitionOutProgress manual:(bool)manual
|
|
{
|
|
[_captionMixin onAnimateOut];
|
|
if (transitionOutProgress > FLT_EPSILON)
|
|
[self setAllInterfaceHidden:true delay:0.0 animated:true];
|
|
else if (!manual)
|
|
[self setAllInterfaceHidden:false delay:0.0 animated:true];
|
|
}
|
|
|
|
- (void)setToolbarsHidden:(bool)hidden animated:(bool)animated
|
|
{
|
|
if (hidden)
|
|
{
|
|
[_portraitToolbarView transitionOutAnimated:animated transparent:true hideOnCompletion:false];
|
|
[_landscapeToolbarView transitionOutAnimated:animated transparent:true hideOnCompletion:false];
|
|
}
|
|
else
|
|
{
|
|
[_portraitToolbarView transitionInAnimated:animated transparent:true];
|
|
[_landscapeToolbarView transitionInAnimated:animated transparent:true];
|
|
}
|
|
}
|
|
|
|
- (void)immediateEditorTransitionIn {
|
|
[self setSelectionInterfaceHidden:true animated:false];
|
|
_captionMixin.inputPanelView.alpha = 0.0f;
|
|
_captionMixin.backgroundView.alpha = 0.0f;
|
|
_portraitToolbarView.doneButton.alpha = 0.0f;
|
|
_landscapeToolbarView.doneButton.alpha = 0.0f;
|
|
|
|
_portraitToolbarView.hidden = true;
|
|
_landscapeToolbarView.hidden = true;
|
|
|
|
TGDispatchAfter(0.5, dispatch_get_main_queue(), ^
|
|
{
|
|
_portraitToolbarView.hidden = false;
|
|
_landscapeToolbarView.hidden = false;
|
|
});
|
|
}
|
|
|
|
- (void)editorTransitionIn
|
|
{
|
|
[self setSelectionInterfaceHidden:true animated:true];
|
|
|
|
[UIView animateWithDuration:0.2 animations:^
|
|
{
|
|
_captionMixin.inputPanelView.alpha = 0.0f;
|
|
_captionMixin.backgroundView.alpha = 0.0f;
|
|
_portraitToolbarView.doneButton.alpha = 0.0f;
|
|
_landscapeToolbarView.doneButton.alpha = 0.0f;
|
|
}];
|
|
}
|
|
|
|
- (void)editorTransitionOut
|
|
{
|
|
[self setSelectionInterfaceHidden:false animated:true];
|
|
|
|
[UIView animateWithDuration:0.3 animations:^
|
|
{
|
|
_captionMixin.inputPanelView.alpha = 1.0f;
|
|
_captionMixin.backgroundView.alpha = 1.0f;
|
|
_portraitToolbarView.doneButton.alpha = 1.0f;
|
|
_landscapeToolbarView.doneButton.alpha = 1.0f;
|
|
}];
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
|
{
|
|
UIView *view = [super hitTest:point withEvent:event];
|
|
|
|
if (view == _photoCounterButton
|
|
|| view == _checkButton
|
|
|| view == _muteButton
|
|
|| view == _telescopeButton
|
|
|| view == _groupButton
|
|
|| view == _cameraButton
|
|
|| [view isDescendantOfView:_headerWrapperView]
|
|
|| [view isDescendantOfView:_portraitToolbarView]
|
|
|| [view isDescendantOfView:_landscapeToolbarView]
|
|
|| [view isDescendantOfView:_selectedPhotosView]
|
|
|| [view isDescendantOfView:_captionMixin.inputPanelView]
|
|
|| ([view isDescendantOfView:_captionMixin.dismissView] && _captionMixin.dismissView.alpha > 0.0)
|
|
|| [view isKindOfClass:[TGMenuButtonView class]])
|
|
|
|
{
|
|
return view;
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
- (bool)prefersStatusBarHidden
|
|
{
|
|
return true;
|
|
}
|
|
|
|
- (bool)allowsHide
|
|
{
|
|
return true;
|
|
}
|
|
|
|
- (bool)showHiddenInterfaceOnScroll
|
|
{
|
|
return true;
|
|
}
|
|
|
|
- (bool)allowsDismissalWithSwipeGesture
|
|
{
|
|
return self.hasSwipeGesture;
|
|
}
|
|
|
|
- (bool)shouldAutorotate
|
|
{
|
|
return true;
|
|
}
|
|
|
|
- (CGRect)_muteButtonFrameForOrientation:(UIInterfaceOrientation)orientation screenEdges:(UIEdgeInsets)screenEdges hasHeaderView:(bool)hasHeaderView
|
|
{
|
|
CGRect frame = CGRectZero;
|
|
if (_safeAreaInset.top > 20.0f)
|
|
screenEdges.top += _safeAreaInset.top;
|
|
screenEdges.left += _safeAreaInset.left;
|
|
screenEdges.right -= _safeAreaInset.right;
|
|
|
|
CGFloat panelInset = 0.0f;
|
|
|
|
switch (orientation)
|
|
{
|
|
case UIInterfaceOrientationLandscapeLeft:
|
|
frame = CGRectMake(screenEdges.right - 47, screenEdges.bottom - 54 - 59, _muteButton.frame.size.width, _muteButton.frame.size.height);
|
|
break;
|
|
|
|
case UIInterfaceOrientationLandscapeRight:
|
|
frame = CGRectMake(screenEdges.left + 5, screenEdges.bottom - 54 - 59, _muteButton.frame.size.width, _muteButton.frame.size.height);
|
|
break;
|
|
|
|
default:
|
|
frame = CGRectMake(screenEdges.left + 5, screenEdges.bottom - TGPhotoEditorToolbarSize - [_captionMixin.inputPanel baseHeight] - 45 - _safeAreaInset.bottom - panelInset - (hasHeaderView ? 64.0 : 0.0), _muteButton.frame.size.width, _muteButton.frame.size.height);
|
|
break;
|
|
}
|
|
|
|
return frame;
|
|
}
|
|
|
|
|
|
- (CGRect)_telescopeButtonFrameForOrientation:(UIInterfaceOrientation)orientation screenEdges:(UIEdgeInsets)screenEdges hasHeaderView:(bool)hasHeaderView
|
|
{
|
|
CGRect frame = CGRectZero;
|
|
if (_safeAreaInset.top > 20.0f)
|
|
screenEdges.top += _safeAreaInset.top;
|
|
screenEdges.left += _safeAreaInset.left;
|
|
screenEdges.right -= _safeAreaInset.right;
|
|
|
|
CGFloat panelInset = 0.0f;
|
|
|
|
CGRect muteButtonFrame = [self _muteButtonFrameForOrientation:orientation screenEdges:screenEdges hasHeaderView:hasHeaderView];
|
|
|
|
switch (orientation)
|
|
{
|
|
case UIInterfaceOrientationLandscapeLeft:
|
|
frame = CGRectMake(screenEdges.right - 47, muteButtonFrame.origin.y - muteButtonFrame.size.height - 5, _telescopeButton.frame.size.width, _telescopeButton.frame.size.height);
|
|
break;
|
|
|
|
case UIInterfaceOrientationLandscapeRight:
|
|
frame = CGRectMake(screenEdges.left + 5, muteButtonFrame.origin.y - muteButtonFrame.size.height - 5, _telescopeButton.frame.size.width, _telescopeButton.frame.size.height);
|
|
break;
|
|
|
|
default:
|
|
frame = CGRectMake(muteButtonFrame.origin.x + muteButtonFrame.size.width + 5, screenEdges.bottom - TGPhotoEditorToolbarSize - [_captionMixin.inputPanel baseHeight] - 45 - _safeAreaInset.bottom - panelInset - (hasHeaderView ? 64.0 : 0.0), _telescopeButton.frame.size.width, _telescopeButton.frame.size.height);
|
|
break;
|
|
}
|
|
|
|
return frame;
|
|
}
|
|
|
|
- (CGRect)_groupButtonFrameForOrientation:(UIInterfaceOrientation)orientation screenEdges:(UIEdgeInsets)screenEdges hasHeaderView:(bool)hasHeaderView
|
|
{
|
|
CGRect frame = CGRectZero;
|
|
if (_safeAreaInset.top > 20.0f)
|
|
screenEdges.top += _safeAreaInset.top;
|
|
screenEdges.left += _safeAreaInset.left;
|
|
screenEdges.right -= _safeAreaInset.right;
|
|
screenEdges.bottom -= _safeAreaInset.bottom;
|
|
|
|
switch (orientation)
|
|
{
|
|
case UIInterfaceOrientationLandscapeLeft:
|
|
frame = CGRectMake(screenEdges.left + TGPhotoEditorToolbarSize + 14, screenEdges.bottom - _groupButton.frame.size.height - 1.0f + _safeAreaInset.bottom, _groupButton.frame.size.width, _groupButton.frame.size.height);
|
|
break;
|
|
|
|
case UIInterfaceOrientationLandscapeRight:
|
|
frame = CGRectMake(screenEdges.right - TGPhotoEditorToolbarSize - 38 - 14, screenEdges.bottom - _groupButton.frame.size.height - 1.0f + _safeAreaInset.bottom, _groupButton.frame.size.width, _groupButton.frame.size.height);
|
|
break;
|
|
|
|
default:
|
|
frame = CGRectMake(screenEdges.left + 6.0f, screenEdges.bottom - TGPhotoEditorToolbarSize - [_captionMixin.inputPanel baseHeight] - 40.0f, _groupButton.frame.size.width, _groupButton.frame.size.height);
|
|
break;
|
|
}
|
|
|
|
return frame;
|
|
}
|
|
|
|
- (CGRect)_checkButtonFrameForOrientation:(UIInterfaceOrientation)orientation screenEdges:(UIEdgeInsets)screenEdges hasHeaderView:(bool)hasHeaderView
|
|
{
|
|
CGRect frame = CGRectZero;
|
|
if (_safeAreaInset.top > 20.0f)
|
|
screenEdges.top += _safeAreaInset.top;
|
|
screenEdges.left += _safeAreaInset.left;
|
|
screenEdges.right -= _safeAreaInset.right;
|
|
|
|
switch (orientation)
|
|
{
|
|
case UIInterfaceOrientationLandscapeLeft:
|
|
frame = CGRectMake(screenEdges.right - 44, screenEdges.top + 5, _checkButton.frame.size.width, _checkButton.frame.size.height);
|
|
break;
|
|
|
|
case UIInterfaceOrientationLandscapeRight:
|
|
frame = CGRectMake(screenEdges.left + 4, screenEdges.top + 5, _checkButton.frame.size.width, _checkButton.frame.size.height);
|
|
break;
|
|
|
|
default:
|
|
frame = CGRectMake(screenEdges.right - 44, screenEdges.top + 5, _checkButton.frame.size.width, _checkButton.frame.size.height);
|
|
break;
|
|
}
|
|
|
|
return frame;
|
|
}
|
|
|
|
- (CGRect)_cameraButtonFrameForOrientation:(UIInterfaceOrientation)orientation screenEdges:(UIEdgeInsets)screenEdges hasHeaderView:(bool)hasHeaderView panelVisible:(bool)panelVisible
|
|
{
|
|
CGRect frame = CGRectZero;
|
|
if (_safeAreaInset.top > 20.0f)
|
|
screenEdges.top += _safeAreaInset.top;
|
|
screenEdges.left += _safeAreaInset.left;
|
|
screenEdges.right -= _safeAreaInset.right;
|
|
|
|
CGFloat headerInset = hasHeaderView ? 64.0f : 0.0f;
|
|
CGFloat buttonInset = _selectionContext != nil ? 50.0f : 0.0f;
|
|
CGFloat panelInset = 0.0f;
|
|
|
|
switch (orientation)
|
|
{
|
|
case UIInterfaceOrientationLandscapeLeft:
|
|
frame = CGRectMake(screenEdges.left + TGPhotoEditorToolbarSize + 1 + _safeAreaInset.left - 34.0f, screenEdges.top + 1 + headerInset + buttonInset, 44, 44);
|
|
break;
|
|
|
|
case UIInterfaceOrientationLandscapeRight:
|
|
frame = CGRectMake(screenEdges.right - TGPhotoEditorToolbarSize - 1 - _safeAreaInset.right - 11.0f, screenEdges.top + 1 + headerInset + buttonInset, 44, 44);
|
|
break;
|
|
|
|
default:
|
|
frame = CGRectMake(screenEdges.right - 46 - _safeAreaInset.right - buttonInset, screenEdges.bottom - TGPhotoEditorToolbarSize - [_captionMixin.inputPanel baseHeight] - 45 - _safeAreaInset.bottom - panelInset - (hasHeaderView ? 64.0 : 0.0), 44, 44);
|
|
break;
|
|
}
|
|
|
|
return frame;
|
|
}
|
|
|
|
- (void)_layoutRecipientLabelForOrientation:(UIInterfaceOrientation)orientation screenEdges:(UIEdgeInsets)screenEdges hasHeaderView:(bool)hasHeaderView
|
|
{
|
|
CGFloat screenWidth = MIN(self.frame.size.width, self.frame.size.height);
|
|
CGFloat recipientWidth = MIN(_recipientLabel.frame.size.width, screenWidth - 150.0f);
|
|
|
|
CGRect frame = CGRectZero;
|
|
if (_safeAreaInset.top > 20.0f + FLT_EPSILON)
|
|
screenEdges.top += _safeAreaInset.top;
|
|
screenEdges.left += _safeAreaInset.left;
|
|
screenEdges.right -= _safeAreaInset.right;
|
|
|
|
switch (orientation)
|
|
{
|
|
case UIInterfaceOrientationLandscapeLeft:
|
|
frame = CGRectMake(screenEdges.right - recipientWidth - 28.0f, screenEdges.bottom - 24, _arrowView.frame.size.width, _arrowView.frame.size.height);
|
|
break;
|
|
|
|
case UIInterfaceOrientationLandscapeRight:
|
|
frame = CGRectMake(screenEdges.left + 14, screenEdges.bottom - 24, _arrowView.frame.size.width, _arrowView.frame.size.height);
|
|
break;
|
|
|
|
default:
|
|
frame = CGRectMake(screenEdges.left + 14, screenEdges.top + 16, _arrowView.frame.size.width, _arrowView.frame.size.height);
|
|
break;
|
|
}
|
|
|
|
_arrowView.frame = frame;
|
|
_recipientLabel.frame = CGRectMake(CGRectGetMaxX(_arrowView.frame) + 6.0f, _arrowView.frame.origin.y - 2.0f, recipientWidth, _recipientLabel.frame.size.height);
|
|
}
|
|
|
|
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)__unused duration
|
|
{
|
|
_landscapeToolbarView.interfaceOrientation = toInterfaceOrientation;
|
|
[self setNeedsLayout];
|
|
}
|
|
|
|
- (UIInterfaceOrientation)interfaceOrientation
|
|
{
|
|
UIInterfaceOrientation orientation = [[LegacyComponentsGlobals provider] applicationStatusBarOrientation];
|
|
if (self.usesSimpleLayout || TGIsPad())
|
|
orientation = UIInterfaceOrientationPortrait;
|
|
|
|
return orientation;
|
|
}
|
|
|
|
- (CGSize)referenceViewSize
|
|
{
|
|
return [_context fullscreenBounds].size;
|
|
}
|
|
|
|
- (void)setSafeAreaInset:(UIEdgeInsets)safeAreaInset
|
|
{
|
|
_safeAreaInset = safeAreaInset;
|
|
_captionMixin.safeAreaInset = safeAreaInset;
|
|
[_currentItemView setSafeAreaInset:[self localSafeAreaInset]];
|
|
[self setNeedsLayout];
|
|
}
|
|
|
|
- (UIEdgeInsets)localSafeAreaInset
|
|
{
|
|
UIEdgeInsets safeAreaInset = _safeAreaInset;
|
|
if (self.usesSimpleLayout || TGIsPad())
|
|
return safeAreaInset;
|
|
|
|
UIInterfaceOrientation orientation = [self interfaceOrientation];
|
|
if (orientation == UIInterfaceOrientationLandscapeLeft)
|
|
safeAreaInset.left = 0.0f;
|
|
else if (orientation == UIInterfaceOrientationLandscapeRight)
|
|
safeAreaInset.right = 0.0f;
|
|
|
|
return safeAreaInset;
|
|
}
|
|
|
|
- (UIEdgeInsets)screenEdges
|
|
{
|
|
CGSize screenSize = TGScreenSize();
|
|
if (TGIsPad())
|
|
screenSize = [self referenceViewSize];
|
|
CGFloat screenSide = MAX(screenSize.width, screenSize.height);
|
|
UIEdgeInsets screenEdges = UIEdgeInsetsZero;
|
|
|
|
if (TGIsPad())
|
|
{
|
|
screenEdges = UIEdgeInsetsMake(0, 0, self.frame.size.height, self.frame.size.width);
|
|
}
|
|
else
|
|
{
|
|
screenEdges = UIEdgeInsetsMake((screenSide - self.frame.size.height) / 2, (screenSide - self.frame.size.width) / 2, (screenSide + self.frame.size.height) / 2, (screenSide + self.frame.size.width) / 2);
|
|
}
|
|
return screenEdges;
|
|
}
|
|
|
|
- (void)layoutSubviews
|
|
{
|
|
[super layoutSubviews];
|
|
|
|
[_captionMixin setContentAreaHeight:self.frame.size.height];
|
|
|
|
UIInterfaceOrientation orientation = [self interfaceOrientation];
|
|
CGSize screenSize = TGScreenSize();
|
|
if (TGIsPad())
|
|
screenSize = [self referenceViewSize];
|
|
|
|
CGFloat screenSide = MAX(screenSize.width, screenSize.height);
|
|
UIEdgeInsets screenEdges = UIEdgeInsetsZero;
|
|
|
|
if (TGIsPad())
|
|
{
|
|
_landscapeToolbarView.hidden = true;
|
|
screenEdges = UIEdgeInsetsMake(0, 0, self.frame.size.height, self.frame.size.width);
|
|
_wrapperView.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
|
|
}
|
|
else
|
|
{
|
|
screenEdges = UIEdgeInsetsMake((screenSide - self.frame.size.height) / 2, (screenSide - self.frame.size.width) / 2, (screenSide + self.frame.size.height) / 2, (screenSide + self.frame.size.width) / 2);
|
|
_wrapperView.frame = CGRectMake((self.frame.size.width - screenSide) / 2, (self.frame.size.height - screenSide) / 2, screenSide, screenSide);
|
|
}
|
|
|
|
_selectedPhotosView.interfaceOrientation = orientation;
|
|
|
|
CGFloat photosViewSize = TGPhotoThumbnailSizeForCurrentScreen().height + 4 * 2;
|
|
|
|
bool hasHeaderView = (_currentItemView.headerView != nil);
|
|
CGFloat headerInset = hasHeaderView ? 64.0f : 0.0f;
|
|
|
|
CGFloat portraitToolbarViewBottomEdge = screenSide;
|
|
if (self.usesSimpleLayout || TGIsPad())
|
|
portraitToolbarViewBottomEdge = screenEdges.bottom;
|
|
_portraitToolbarView.frame = CGRectMake(screenEdges.left, portraitToolbarViewBottomEdge - TGPhotoEditorToolbarSize - _safeAreaInset.bottom, self.frame.size.width, TGPhotoEditorToolbarSize + _safeAreaInset.bottom);
|
|
|
|
UIEdgeInsets captionEdgeInsets = screenEdges;
|
|
captionEdgeInsets.bottom = _portraitToolbarView.frame.size.height;
|
|
[_captionMixin updateLayoutWithFrame:self.bounds edgeInsets:captionEdgeInsets animated:false];
|
|
|
|
switch (orientation)
|
|
{
|
|
case UIInterfaceOrientationLandscapeLeft:
|
|
{
|
|
[UIView performWithoutAnimation:^
|
|
{
|
|
_photoCounterButton.frame = CGRectMake(screenEdges.left + TGPhotoEditorToolbarSize + 1 + _safeAreaInset.left, screenEdges.top + 6 + headerInset, 64, 38);
|
|
|
|
_selectedPhotosView.frame = CGRectMake(screenEdges.left + TGPhotoEditorToolbarSize + 66 + _safeAreaInset.left, screenEdges.top + 4 + headerInset, photosViewSize, self.frame.size.height - 4 * 2 - headerInset);
|
|
|
|
_landscapeToolbarView.frame = CGRectMake(screenEdges.left + _safeAreaInset.left, screenEdges.top, TGPhotoEditorToolbarSize + _safeAreaInset.left, self.frame.size.height);
|
|
}];
|
|
|
|
_headerWrapperView.frame = CGRectMake(screenEdges.left + TGPhotoEditorToolbarSize + _safeAreaInset.left, screenEdges.top, self.frame.size.width - TGPhotoEditorToolbarSize - _safeAreaInset.left, 64);
|
|
}
|
|
break;
|
|
|
|
case UIInterfaceOrientationLandscapeRight:
|
|
{
|
|
[UIView performWithoutAnimation:^
|
|
{
|
|
_photoCounterButton.frame = CGRectMake(screenEdges.right - TGPhotoEditorToolbarSize - 64 - 1 - _safeAreaInset.right, screenEdges.top + 6 + headerInset, 64, 38);
|
|
|
|
_selectedPhotosView.frame = CGRectMake(screenEdges.right - TGPhotoEditorToolbarSize - photosViewSize - 66 - _safeAreaInset.right, screenEdges.top + 4 + headerInset, photosViewSize, self.frame.size.height - 4 * 2 - headerInset);
|
|
|
|
_landscapeToolbarView.frame = CGRectMake(screenEdges.right - TGPhotoEditorToolbarSize - _safeAreaInset.right, screenEdges.top, TGPhotoEditorToolbarSize + _safeAreaInset.right, self.frame.size.height);
|
|
}];
|
|
|
|
_headerWrapperView.frame = CGRectMake(screenEdges.left, screenEdges.top, self.frame.size.width - TGPhotoEditorToolbarSize - _safeAreaInset.right, 64);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
[UIView performWithoutAnimation:^
|
|
{
|
|
_photoCounterButton.frame = CGRectMake(screenEdges.right - 56 - _safeAreaInset.right, screenEdges.bottom - TGPhotoEditorToolbarSize - [_captionMixin.inputPanel baseHeight] - 40 - _safeAreaInset.bottom - (hasHeaderView ? 64.0 : 0.0), 64, 38);
|
|
|
|
_selectedPhotosView.frame = CGRectMake(screenEdges.left + 4, screenEdges.bottom - TGPhotoEditorToolbarSize - [_captionMixin.inputPanel baseHeight] - photosViewSize - 54 - _safeAreaInset.bottom - (hasHeaderView ? 64.0 : 0.0), self.frame.size.width - 4 * 2 - _safeAreaInset.right, photosViewSize);
|
|
}];
|
|
|
|
_landscapeToolbarView.frame = CGRectMake(_landscapeToolbarView.frame.origin.x, screenEdges.top, TGPhotoEditorToolbarSize, self.frame.size.height);
|
|
|
|
_headerWrapperView.frame = CGRectMake(screenEdges.left, _portraitToolbarView.frame.origin.y - 64.0 - [_captionMixin.inputPanel baseHeight], self.frame.size.width, 64.0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
_muteButton.frame = [self _muteButtonFrameForOrientation:orientation screenEdges:screenEdges hasHeaderView:true];
|
|
_telescopeButton.frame = [self _telescopeButtonFrameForOrientation:orientation screenEdges:screenEdges hasHeaderView:true];
|
|
_checkButton.frame = [self _checkButtonFrameForOrientation:orientation screenEdges:screenEdges hasHeaderView:hasHeaderView];
|
|
_groupButton.frame = [self _groupButtonFrameForOrientation:orientation screenEdges:screenEdges hasHeaderView:hasHeaderView];
|
|
[UIView performWithoutAnimation:^
|
|
{
|
|
_cameraButton.frame = [self _cameraButtonFrameForOrientation:orientation screenEdges:screenEdges hasHeaderView:hasHeaderView panelVisible:_selectedPhotosView != nil && !_selectedPhotosView.isInternalHidden];
|
|
}];
|
|
[self _layoutRecipientLabelForOrientation:orientation screenEdges:screenEdges hasHeaderView:hasHeaderView];
|
|
|
|
for (UIView *itemHeaderView in _itemHeaderViews)
|
|
itemHeaderView.frame = _headerWrapperView.bounds;
|
|
|
|
CGRect itemFooterViewFrame = [self itemFooterViewFrameForSize:self.frame.size];
|
|
for (UIView *itemFooterView in _itemFooterViews)
|
|
itemFooterView.frame = itemFooterViewFrame;
|
|
}
|
|
|
|
- (CGRect)doneButtonFrame {
|
|
if (UIDeviceOrientationIsPortrait((UIDeviceOrientation)[self interfaceOrientation])) {
|
|
return [_portraitToolbarView.doneButton convertRect:_portraitToolbarView.doneButton.bounds toView:nil];
|
|
} else {
|
|
return [_landscapeToolbarView.doneButton convertRect:_landscapeToolbarView.doneButton.bounds toView:nil];
|
|
}
|
|
}
|
|
|
|
@end
|