mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
More memory leak fixes
This commit is contained in:
parent
040e8b2da0
commit
403dd188a4
@ -1189,8 +1189,7 @@ ActionStage *ActionStageInstance()
|
||||
{
|
||||
TGLegacyLog(@"Will cancel request to \"%@\" in %f s", path, cancelTimeout);
|
||||
NSDictionary *cancelDict = [NSDictionary dictionaryWithObjectsAndKeys:path, @"path", [NSNumber numberWithInt:0], @"type", nil];
|
||||
STimer *timer = [[STimer alloc] initWithTimeout:cancelTimeout repeat:false completion:^
|
||||
{
|
||||
STimer *timer = [[STimer alloc] initWithTimeout:cancelTimeout repeat:false completion:^(__unused STimer *timer) {
|
||||
[self performCancelRequest:cancelDict];
|
||||
} nativeQueue:[ActionStageInstance() globalStageDispatchQueue]];
|
||||
|
||||
|
@ -96,7 +96,7 @@
|
||||
|
||||
[self setChecked:[self.selectionContext isItemSelected:(id<TGMediaSelectableItem>)asset] animated:false];
|
||||
__weak TGAttachmentAssetCell *weakSelf = self;
|
||||
[_itemSelectedDisposable setDisposable:[[self.selectionContext itemInformativeSelectedSignal:(id<TGMediaSelectableItem>)asset] startWithNext:^(TGMediaSelectionChange *next)
|
||||
[_itemSelectedDisposable setDisposable:[[self.selectionContext itemInformativeSelectedSignal:(id<TGMediaSelectableItem>)asset] startStrictWithNext:^(TGMediaSelectionChange *next)
|
||||
{
|
||||
__strong TGAttachmentAssetCell *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -104,7 +104,7 @@
|
||||
|
||||
if (next.sender != strongSelf->_checkButton)
|
||||
[strongSelf setChecked:next.selected animated:next.animated];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
if (_asset == nil)
|
||||
|
@ -174,7 +174,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
return [SSignal complete];
|
||||
|
||||
return [[strongSelf->_collectionView noOngoingTransitionSignal] then:[SSignal single:value]];
|
||||
}] startWithNext:^(__unused TGMediaSelectionChange *change)
|
||||
}] startStrictWithNext:^(__unused TGMediaSelectionChange *change)
|
||||
{
|
||||
__strong TGAttachmentCarouselItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -190,7 +190,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
[strongSelf updateSendButtonsFromIndex:index];
|
||||
|
||||
[strongSelf updateSelectionIndexes];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
if (allowEditing)
|
||||
@ -198,7 +198,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
_editingContext = [[TGMediaEditingContext alloc] init];
|
||||
|
||||
_itemsSizeChangedDisposable = [[SMetaDisposable alloc] init];
|
||||
[_itemsSizeChangedDisposable setDisposable:[[[_editingContext cropAdjustmentsUpdatedSignal] deliverOn:[SQueue mainQueue]] startWithNext:^(__unused id next)
|
||||
[_itemsSizeChangedDisposable setDisposable:[[[_editingContext cropAdjustmentsUpdatedSignal] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(__unused id next)
|
||||
{
|
||||
__strong TGAttachmentCarouselItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -217,7 +217,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
[strongSelf centerOnItemWithIndex:indexPath.row animated:false];
|
||||
}
|
||||
}
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
_smallLayout = [[UICollectionViewFlowLayout alloc] init];
|
||||
@ -430,7 +430,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
return [SSignal complete];
|
||||
|
||||
return [[strongSelf->_collectionView noOngoingTransitionSignal] then:[SSignal single:value]];
|
||||
}] deliverOn:[SQueue mainQueue]] startWithNext:^(id next)
|
||||
}] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id next)
|
||||
{
|
||||
__strong TGAttachmentCarouselItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -456,7 +456,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
|
||||
if (strongSelf->_galleryMixin != nil && strongSelf->_fetchResult != nil)
|
||||
[strongSelf->_galleryMixin updateWithFetchResult:strongSelf->_fetchResult];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (SSignal *)_signalForItem:(TGMediaAsset *)asset
|
||||
|
@ -64,7 +64,7 @@ NSString *const TGAttachmentVideoCellIdentifier = @"AttachmentVideoCell";
|
||||
SSignal *adjustmentsSignal = [self.editingContext adjustmentsSignalForItem:self.asset];
|
||||
|
||||
__weak TGAttachmentVideoCell *weakSelf = self;
|
||||
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startWithNext:^(TGVideoEditAdjustments *next)
|
||||
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startStrictWithNext:^(TGVideoEditAdjustments *next)
|
||||
{
|
||||
__strong TGAttachmentVideoCell *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -74,7 +74,7 @@ NSString *const TGAttachmentVideoCellIdentifier = @"AttachmentVideoCell";
|
||||
[strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation];
|
||||
else
|
||||
[strongSelf _layoutImageWithoutAdjustments];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (void)_transformLayoutForOrientation:(UIImageOrientation)orientation originalSize:(CGSize *)inOriginalSize cropRect:(CGRect *)inCropRect
|
||||
|
@ -304,7 +304,7 @@ NSString *TGImageViewOptionSynchronous = @"TGImageViewOptionSynchronous";
|
||||
int version = _version;
|
||||
__weak TGImageView *weakSelf = self;
|
||||
|
||||
[_disposable setDisposable:[signal startWithNext:^(id next)
|
||||
[_disposable setDisposable:[signal startStrictWithNext:^(id next)
|
||||
{
|
||||
bool synchronous = [NSThread isMainThread];
|
||||
TGDispatchOnMainThread(^
|
||||
@ -323,7 +323,7 @@ NSString *TGImageViewOptionSynchronous = @"TGImageViewOptionSynchronous";
|
||||
TGLegacyLog(@"TGImageView signal error: %@", error);
|
||||
} completed:^
|
||||
{
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -639,8 +639,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
STimer *progressTimer = [[STimer alloc] initWithTimeout:0.5 repeat:true completion:^
|
||||
{
|
||||
STimer *progressTimer = [[STimer alloc] initWithTimeout:0.5 repeat:true completion:^(__unused STimer *timer) {
|
||||
[subscriber putNext:@(exportSession.progress)];
|
||||
} queue:[SQueue concurrentDefaultQueue]];
|
||||
[progressTimer start];
|
||||
|
@ -491,7 +491,7 @@
|
||||
};
|
||||
|
||||
_selectionChangedDisposable = [[SMetaDisposable alloc] init];
|
||||
[_selectionChangedDisposable setDisposable:[[_selectionContext selectionChangedSignal] startWithNext:^(__unused id next)
|
||||
[_selectionChangedDisposable setDisposable:[[_selectionContext selectionChangedSignal] startStrictWithNext:^(__unused id next)
|
||||
{
|
||||
__strong TGMediaAssetsController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -540,7 +540,7 @@
|
||||
}
|
||||
|
||||
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, text);
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
|
||||
if (intent == TGMediaAssetsControllerSendMediaIntent || intent == TGMediaAssetsControllerSetProfilePhotoIntent || intent == TGMediaAssetsControllerSetSignupProfilePhotoIntent || intent == TGMediaAssetsControllerPassportIntent || intent == TGMediaAssetsControllerPassportMultipleIntent)
|
||||
_editingContext = [[TGMediaEditingContext alloc] init];
|
||||
@ -550,28 +550,28 @@
|
||||
if (allowGrouping)
|
||||
{
|
||||
_groupingChangedDisposable = [[SMetaDisposable alloc] init];
|
||||
[_groupingChangedDisposable setDisposable:[_selectionContext.groupingChangedSignal startWithNext:^(NSNumber *next)
|
||||
[_groupingChangedDisposable setDisposable:[_selectionContext.groupingChangedSignal startStrictWithNext:^(NSNumber *next)
|
||||
{
|
||||
__strong TGMediaAssetsController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
[strongSelf->_toolbarView setCenterButtonSelected:next.boolValue];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
|
||||
if (_editingContext != nil)
|
||||
{
|
||||
_timersChangedDisposable = [[SMetaDisposable alloc] init];
|
||||
[_timersChangedDisposable setDisposable:[_editingContext.timersUpdatedSignal startWithNext:^(__unused NSNumber *next)
|
||||
[_timersChangedDisposable setDisposable:[_editingContext.timersUpdatedSignal startStrictWithNext:^(__unused NSNumber *next)
|
||||
{
|
||||
updateGroupingButtonVisibility();
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
|
||||
_adjustmentsChangedDisposable = [[SMetaDisposable alloc] init];
|
||||
[_adjustmentsChangedDisposable setDisposable:[_editingContext.adjustmentsUpdatedSignal startWithNext:^(__unused NSNumber *next)
|
||||
[_adjustmentsChangedDisposable setDisposable:[_editingContext.adjustmentsUpdatedSignal startStrictWithNext:^(__unused NSNumber *next)
|
||||
{
|
||||
updateGroupingButtonVisibility();
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1873,11 +1873,11 @@
|
||||
_tooltipDismissDisposable = [[SMetaDisposable alloc] init];
|
||||
|
||||
__weak TGTooltipContainerView *weakContainerView = _groupingTooltipContainerView;
|
||||
[_tooltipDismissDisposable setDisposable:[[[SSignal complete] delay:duration onQueue:[SQueue mainQueue]] startWithNext:nil completed:^{
|
||||
[_tooltipDismissDisposable setDisposable:[[[SSignal complete] delay:duration onQueue:[SQueue mainQueue]] startStrictWithNext:nil completed:^{
|
||||
__strong TGTooltipContainerView *strongContainerView = weakContainerView;
|
||||
if (strongContainerView != nil)
|
||||
[strongContainerView hideTooltip];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (BOOL)prefersStatusBarHidden
|
||||
|
@ -134,12 +134,12 @@
|
||||
return [strongSelf _itemAtIndexPath:indexPath];
|
||||
};
|
||||
|
||||
_selectionChangedDisposable = [[self.selectionContext selectionChangedSignal] startWithNext:^(id next)
|
||||
_selectionChangedDisposable = [[self.selectionContext selectionChangedSignal] startStrictWithNext:^(id next)
|
||||
{
|
||||
__strong TGMediaAssetsPickerController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
return [strongSelf updateSelectionIndexes];
|
||||
}];
|
||||
} file:__FILE_NAME__ line:__LINE__];
|
||||
}
|
||||
|
||||
- (void)updateSelectionIndexes
|
||||
@ -194,7 +194,7 @@
|
||||
[strongSelf setTitle:assetGroup.title];
|
||||
}
|
||||
return [strongSelf->_assetsLibrary assetsOfAssetGroup:assetGroup reversed:reversed];
|
||||
}] deliverOn:[SQueue mainQueue]] startWithNext:^(id next)
|
||||
}] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id next)
|
||||
{
|
||||
__strong TGMediaAssetsPickerController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -238,7 +238,7 @@
|
||||
|
||||
if (strongSelf->_galleryMixin != nil && strongSelf->_fetchResult != nil)
|
||||
[strongSelf->_galleryMixin updateWithFetchResult:strongSelf->_fetchResult];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
|
@ -112,7 +112,7 @@ NSString *const TGMediaAssetsVideoCellKind = @"TGMediaAssetsVideoCellKind";
|
||||
SSignal *adjustmentsSignal = [self.editingContext adjustmentsSignalForItem:(id<TGMediaEditableItem>)self.item];
|
||||
|
||||
__weak TGMediaAssetsVideoCell *weakSelf = self;
|
||||
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startWithNext:^(TGVideoEditAdjustments *next)
|
||||
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startStrictWithNext:^(TGVideoEditAdjustments *next)
|
||||
{
|
||||
__strong TGMediaAssetsVideoCell *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -122,7 +122,7 @@ NSString *const TGMediaAssetsVideoCellKind = @"TGMediaAssetsVideoCellKind";
|
||||
[strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation];
|
||||
else
|
||||
[strongSelf _layoutImageWithoutAdjustments];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (void)_transformLayoutForOrientation:(UIImageOrientation)orientation originalSize:(CGSize *)inOriginalSize cropRect:(CGRect *)inCropRect
|
||||
|
@ -104,7 +104,7 @@
|
||||
|
||||
__weak TGMediaGroupsController *weakSelf = self;
|
||||
_groupsDisposable = [[SMetaDisposable alloc] init];
|
||||
[_groupsDisposable setDisposable:[[[_assetsLibrary assetGroups] deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *next)
|
||||
[_groupsDisposable setDisposable:[[[_assetsLibrary assetGroups] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSArray *next)
|
||||
{
|
||||
__strong TGMediaGroupsController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -131,7 +131,7 @@
|
||||
if (![next containsObject:pickerController.assetGroup])
|
||||
[strongSelf.navigationController popToRootViewControllerAnimated:false];
|
||||
}
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
|
@ -80,7 +80,7 @@
|
||||
|
||||
__weak TGMediaPickerCell *weakSelf = self;
|
||||
[self setChecked:[self.selectionContext isItemSelected:(id<TGMediaSelectableItem>)item] animated:false];
|
||||
[_itemSelectedDisposable setDisposable:[[self.selectionContext itemInformativeSelectedSignal:(id<TGMediaSelectableItem>)item] startWithNext:^(TGMediaSelectionChange *next)
|
||||
[_itemSelectedDisposable setDisposable:[[self.selectionContext itemInformativeSelectedSignal:(id<TGMediaSelectableItem>)item] startStrictWithNext:^(TGMediaSelectionChange *next)
|
||||
{
|
||||
__strong TGMediaPickerCell *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -88,7 +88,7 @@
|
||||
|
||||
if (next.sender != strongSelf->_checkButton)
|
||||
[strongSelf setChecked:next.selected animated:next.animated];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
if (_item == nil)
|
||||
|
@ -134,6 +134,12 @@
|
||||
|
||||
_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;
|
||||
@ -255,7 +261,7 @@
|
||||
_photoCounterButton.userInteractionEnabled = false;
|
||||
[_wrapperView addSubview:_photoCounterButton];
|
||||
|
||||
_selectionChangedDisposable = [[_selectionContext selectionChangedSignal] startWithNext:^(id next)
|
||||
_selectionChangedDisposable = [[_selectionContext selectionChangedSignal] startStrictWithNext:^(id next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -269,29 +275,29 @@
|
||||
[strongSelf->_checkButton setNumber:[strongSelf->_selectionContext indexOfItem:selectableItem]];
|
||||
|
||||
[strongSelf updateGroupingButtonVisibility];
|
||||
}];
|
||||
} file:__FILE_NAME__ line:__LINE__];
|
||||
|
||||
if (_selectionContext.allowGrouping)
|
||||
{
|
||||
if (_editingContext != nil)
|
||||
{
|
||||
_timersChangedDisposable = [_editingContext.timersUpdatedSignal startWithNext:^(__unused NSNumber *next)
|
||||
_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 startWithNext:^(__unused NSNumber *next)
|
||||
_adjustmentsChangedDisposable = [_editingContext.adjustmentsUpdatedSignal startStrictWithNext:^(__unused NSNumber *next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
[strongSelf updateGroupingButtonVisibility];
|
||||
}];
|
||||
} file:__FILE_NAME__ line:__LINE__];
|
||||
}
|
||||
|
||||
[self updateGroupingButtonVisibility];
|
||||
@ -300,11 +306,6 @@
|
||||
|
||||
[self updateEditorButtonsForItem:focusItem animated:false];
|
||||
|
||||
_adjustmentsDisposable = [[SMetaDisposable alloc] init];
|
||||
_captionDisposable = [[SMetaDisposable alloc] init];
|
||||
_itemSelectedDisposable = [[SMetaDisposable alloc] init];
|
||||
_itemAvailabilityDisposable = [[SMetaDisposable alloc] init];
|
||||
|
||||
_captionMixin = [[TGPhotoCaptionInputMixin alloc] init];
|
||||
_captionMixin.panelParentView = ^UIView *
|
||||
{
|
||||
@ -418,6 +419,7 @@
|
||||
[_itemAvailabilityDisposable dispose];
|
||||
[_selectionChangedDisposable dispose];
|
||||
[_timersChangedDisposable dispose];
|
||||
[_adjustmentsChangedDisposable dispose];
|
||||
}
|
||||
|
||||
- (bool)updateGroupingButtonVisibility
|
||||
@ -566,7 +568,7 @@
|
||||
}
|
||||
[_checkButton setNumber:[_selectionContext indexOfItem:selectableItem]];
|
||||
signal = [_selectionContext itemInformativeSelectedSignal:selectableItem];
|
||||
[_itemSelectedDisposable setDisposable:[signal startWithNext:^(TGMediaSelectionChange *next)
|
||||
[_itemSelectedDisposable setDisposable:[signal startStrictWithNext:^(TGMediaSelectionChange *next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -574,13 +576,13 @@
|
||||
|
||||
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]] startWithNext:^(id next)
|
||||
[_itemAvailabilityDisposable setDisposable:[[[itemView contentAvailabilityStateSignal] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
||||
__strong TGModernGalleryItemView *strongItemView = weakItemView;
|
||||
@ -611,7 +613,7 @@
|
||||
}
|
||||
strongSelf->_muteButton.hidden = !sendableAsGif;
|
||||
}
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
|
||||
UIImage *muteIcon = [TGPhotoEditorInterfaceAssets muteIcon];
|
||||
UIImage *muteActiveIcon = [TGPhotoEditorInterfaceAssets muteActiveIcon];
|
||||
@ -764,13 +766,13 @@
|
||||
if ([item conformsToProtocol:@protocol(TGModernGalleryEditableItem)])
|
||||
{
|
||||
id<TGMediaEditableItem> editableMediaItem = [galleryEditableItem editableMediaItem];
|
||||
[_captionDisposable setDisposable:[[galleryEditableItem.editingContext captionSignalForItem:editableMediaItem] startWithNext:^(NSAttributedString *caption)
|
||||
[_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)
|
||||
@ -829,7 +831,7 @@
|
||||
} else {
|
||||
return [SSignal never];
|
||||
}
|
||||
}] deliverOn:[SQueue mainQueue]] startWithNext:^(NSDictionary *dict)
|
||||
}] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSDictionary *dict)
|
||||
{
|
||||
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -855,7 +857,7 @@
|
||||
originalSize = editableMediaItem.originalSize;
|
||||
|
||||
[strongSelf updateEditorButtonsForAdjustments:adjustments dimensions:originalSize timer:timer];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -215,7 +215,7 @@
|
||||
}];
|
||||
|
||||
SSignal *adjustmentsSignal = [item.editingContext adjustmentsSignalForItem:item.editableMediaItem];
|
||||
[_adjustmentsDisposable setDisposable:[[adjustmentsSignal deliverOn:[SQueue mainQueue]] startWithNext:^(__unused id<TGMediaEditAdjustments> next)
|
||||
[_adjustmentsDisposable setDisposable:[[adjustmentsSignal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(__unused id<TGMediaEditAdjustments> next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryPhotoItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -223,7 +223,7 @@
|
||||
|
||||
[strongSelf layoutEntities];
|
||||
[strongSelf->_entitiesView setupWithEntitiesData:next.paintingData.entitiesData];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
if (item.immediateThumbnailImage != nil)
|
||||
@ -249,7 +249,7 @@
|
||||
}]];
|
||||
|
||||
if (!item.asFile) {
|
||||
[_facesDisposable setDisposable:[[TGPaintFaceDetector detectFacesInItem:item.editableMediaItem editingContext:item.editingContext] startWithNext:nil]];
|
||||
[_facesDisposable setDisposable:[[TGPaintFaceDetector detectFacesInItem:item.editableMediaItem editingContext:item.editingContext] startStrictWithNext:nil file:__FILE_NAME__ line:__LINE__]];
|
||||
|
||||
return;
|
||||
}
|
||||
@ -261,7 +261,7 @@
|
||||
|
||||
if ([item.asset isKindOfClass:[TGMediaAsset class]])
|
||||
{
|
||||
[_attributesDisposable setDisposable:[[[TGMediaAssetImageSignals fileAttributesForAsset:(TGMediaAsset *)item.asset] deliverOn:[SQueue mainQueue]] startWithNext:^(TGMediaAssetImageFileAttributes *next)
|
||||
[_attributesDisposable setDisposable:[[[TGMediaAssetImageSignals fileAttributesForAsset:(TGMediaAsset *)item.asset] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(TGMediaAssetImageFileAttributes *next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryPhotoItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -276,7 +276,7 @@
|
||||
} else {
|
||||
strongSelf->_fileInfoLabel.text = dimensions;
|
||||
}
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
||||
{
|
||||
__weak TGMediaPickerGallerySelectedItemsModel *weakSelf = self;
|
||||
_selectionChangedDisposable = [[SMetaDisposable alloc] init];
|
||||
[_selectionChangedDisposable setDisposable:[[selectionContext selectionChangedSignal] startWithNext:^(TGMediaSelectionChange *next)
|
||||
[_selectionChangedDisposable setDisposable:[[selectionContext selectionChangedSignal] startStrictWithNext:^(TGMediaSelectionChange *next)
|
||||
{
|
||||
__strong TGMediaPickerGallerySelectedItemsModel *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -53,7 +53,7 @@
|
||||
[strongSelf addSelectedItem:next.item];
|
||||
else if (!strongSelf->_keepItems)
|
||||
[strongSelf removeSelectedItem:next.item];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
|
@ -354,7 +354,7 @@
|
||||
[self setProgressVisible:true value:0.027 animated:true];
|
||||
|
||||
__weak TGMediaPickerGalleryVideoItemView *weakSelf = self;
|
||||
[_downloadDisposable setDisposable:[[[TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)self.item.asset allowNetworkAccess:true] deliverOn:[SQueue mainQueue]] startWithNext:^(id next)
|
||||
[_downloadDisposable setDisposable:[[[TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)self.item.asset allowNetworkAccess:true] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -379,7 +379,7 @@
|
||||
strongSelf->_downloaded = true;
|
||||
if (strongSelf->_currentAvailabilityObserver != nil)
|
||||
strongSelf->_currentAvailabilityObserver(true);
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (id<TGModernGalleryItem>)item {
|
||||
@ -413,7 +413,7 @@
|
||||
[self _playerCleanup];
|
||||
|
||||
if (!item.asFile) {
|
||||
[_facesDisposable setDisposable:[[TGPaintFaceDetector detectFacesInItem:item.editableMediaItem editingContext:item.editingContext] startWithNext:nil]];
|
||||
[_facesDisposable setDisposable:[[TGPaintFaceDetector detectFacesInItem:item.editableMediaItem editingContext:item.editingContext] startStrictWithNext:nil file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,7 +489,7 @@
|
||||
SSignal *adjustmentsSignal = [[self editableItemSignal] mapToSignal:^SSignal *(id<TGMediaEditableItem> editableItem) {
|
||||
return [item.editingContext adjustmentsSignalForItem:editableItem];
|
||||
}];
|
||||
[_adjustmentsDisposable setDisposable:[[adjustmentsSignal deliverOn:[SQueue mainQueue]] startWithNext:^(id<TGMediaEditAdjustments> adjustments)
|
||||
[_adjustmentsDisposable setDisposable:[[adjustmentsSignal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id<TGMediaEditAdjustments> adjustments)
|
||||
{
|
||||
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -512,7 +512,7 @@
|
||||
if (!strongSelf.isPlaying) {
|
||||
[strongSelf->_photoEditor reprocess];
|
||||
}
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -532,7 +532,7 @@
|
||||
}
|
||||
|
||||
_fileInfoLabel.text = nil;
|
||||
[_attributesDisposable setDisposable:[[[TGMediaAssetImageSignals fileAttributesForAsset:asset] deliverOn:[SQueue mainQueue]] startWithNext:^(TGMediaAssetImageFileAttributes *next)
|
||||
[_attributesDisposable setDisposable:[[[TGMediaAssetImageSignals fileAttributesForAsset:asset] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(TGMediaAssetImageFileAttributes *next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -546,7 +546,7 @@
|
||||
[components addObject:[TGMediaPickerGalleryVideoItemView _stringForDimensions:next.dimensions]];
|
||||
|
||||
strongSelf->_fileInfoLabel.text = [components componentsJoinedByString:@" • "];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (void)setIsCurrent:(bool)isCurrent
|
||||
@ -576,7 +576,7 @@
|
||||
__weak TGMediaPickerGalleryVideoItemView *weakSelf = self;
|
||||
void (^block)(void) = ^
|
||||
{
|
||||
[_videoDurationDisposable setDisposable:[[_videoDurationVar.signal deliverOn:[SQueue mainQueue]] startWithNext:^(NSNumber *next)
|
||||
[_videoDurationDisposable setDisposable:[[_videoDurationVar.signal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSNumber *next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil || next == nil)
|
||||
@ -611,7 +611,7 @@
|
||||
[strongSelf->_scrubberView resetToStart];
|
||||
strongSelf->_appeared = true;
|
||||
}
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
};
|
||||
|
||||
if (_scrubberView.frame.size.width < FLT_EPSILON)
|
||||
@ -1151,7 +1151,7 @@
|
||||
}];
|
||||
}
|
||||
|
||||
[_playerItemDisposable setDisposable:[[itemSignal deliverOn:[SQueue mainQueue]] startWithNext:^(AVPlayerItem *playerItem)
|
||||
[_playerItemDisposable setDisposable:[[itemSignal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(AVPlayerItem *playerItem)
|
||||
{
|
||||
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil || ![playerItem isKindOfClass:[AVPlayerItem class]])
|
||||
@ -1206,7 +1206,7 @@
|
||||
[strongSelf positionTimerEvent];
|
||||
|
||||
[strongSelf _mutePlayer:strongSelf->_sendAsGif];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)__unused change context:(void *)__unused context
|
||||
@ -1682,7 +1682,7 @@
|
||||
} else {
|
||||
return images;
|
||||
}
|
||||
}] deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *images)
|
||||
}] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSArray *images)
|
||||
{
|
||||
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -1698,7 +1698,7 @@
|
||||
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
strongSelf->_requestingThumbnails = false;
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (void)videoScrubberDidFinishRequestingThumbnails:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber
|
||||
|
@ -149,7 +149,7 @@ NSString *const TGMediaPickerPhotoStripCellKind = @"PhotoStripCell";
|
||||
|
||||
[self setChecked:[self.selectionContext isItemSelected:(id<TGMediaSelectableItem>)item] animated:false];
|
||||
__weak TGMediaPickerPhotoStripCell *weakSelf = self;
|
||||
[_itemSelectedDisposable setDisposable:[[self.selectionContext itemInformativeSelectedSignal:(id<TGMediaSelectableItem>)item] startWithNext:^(TGMediaSelectionChange *next)
|
||||
[_itemSelectedDisposable setDisposable:[[self.selectionContext itemInformativeSelectedSignal:(id<TGMediaSelectableItem>)item] startStrictWithNext:^(TGMediaSelectionChange *next)
|
||||
{
|
||||
__strong TGMediaPickerPhotoStripCell *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -157,7 +157,7 @@ NSString *const TGMediaPickerPhotoStripCellKind = @"PhotoStripCell";
|
||||
|
||||
if (![next.sender isKindOfClass:[TGMediaPickerGallerySelectedItemsModel class]])
|
||||
[strongSelf setChecked:next.selected animated:next.animated];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,7 +181,7 @@ NSString *const TGMediaPickerPhotoStripCellKind = @"PhotoStripCell";
|
||||
SSignal *adjustmentsSignal = [self.editingContext adjustmentsSignalForItem:video];
|
||||
|
||||
__weak TGMediaPickerPhotoStripCell *weakSelf = self;
|
||||
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startWithNext:^(TGVideoEditAdjustments *next)
|
||||
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startStrictWithNext:^(TGVideoEditAdjustments *next)
|
||||
{
|
||||
__strong TGMediaPickerPhotoStripCell *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -191,7 +191,7 @@ NSString *const TGMediaPickerPhotoStripCellKind = @"PhotoStripCell";
|
||||
[strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation];
|
||||
else
|
||||
[strongSelf _layoutImageWithoutAdjustments];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -221,7 +221,7 @@ NSString *const TGMediaPickerPhotoStripCellKind = @"PhotoStripCell";
|
||||
SSignal *adjustmentsSignal = [self.editingContext adjustmentsSignalForItem:asset];
|
||||
|
||||
__weak TGMediaPickerPhotoStripCell *weakSelf = self;
|
||||
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startWithNext:^(TGVideoEditAdjustments *next)
|
||||
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startStrictWithNext:^(TGVideoEditAdjustments *next)
|
||||
{
|
||||
__strong TGMediaPickerPhotoStripCell *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -231,7 +231,7 @@ NSString *const TGMediaPickerPhotoStripCellKind = @"PhotoStripCell";
|
||||
[strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation];
|
||||
else
|
||||
[strongSelf _layoutImageWithoutAdjustments];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -282,7 +282,7 @@
|
||||
return strongSelf.updatedItemsSignal(selectedItems);
|
||||
|
||||
return [SSignal fail:nil];
|
||||
}] deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *next)
|
||||
}] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSArray *next)
|
||||
{
|
||||
__strong TGMediaSelectionContext *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -304,7 +304,7 @@
|
||||
|
||||
for (NSString *identifier in deletedItemsIdentifiers)
|
||||
strongSelf->_pipe.sink([TGMediaSelectionChange changeWithItem:previousItemsMap[identifier] selected:false animated:false sender:nil]);
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
@ -140,7 +140,7 @@ typedef enum
|
||||
|
||||
__weak TGMenuSheetController *weakSelf = self;
|
||||
_sizeClassDisposable = [[SMetaDisposable alloc] init];
|
||||
[_sizeClassDisposable setDisposable:[[_context sizeClassSignal] startWithNext:^(NSNumber *next)
|
||||
[_sizeClassDisposable setDisposable:[[_context sizeClassSignal] startStrictWithNext:^(NSNumber *next)
|
||||
{
|
||||
__strong TGMenuSheetController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -148,7 +148,7 @@ typedef enum
|
||||
|
||||
UIUserInterfaceSizeClass sizeClass = next.integerValue;
|
||||
[strongSelf updateTraitsWithSizeClass:sizeClass];
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
|
||||
_containerView = [[TGMenuSheetContainerView alloc] initWithFrame:CGRectZero];
|
||||
[self.view addSubview:_containerView];
|
||||
|
@ -661,7 +661,7 @@ static void adjustFrameRate(CAAnimation *animation) {
|
||||
if (_asyncTransitionIn) {
|
||||
__weak TGModernGalleryController *weakSelf = self;
|
||||
self.view.hidden = true;
|
||||
_transitionInDisposable = [[[[transitionFromItemView readyForTransitionIn] take:1] timeout:1.0 onQueue:[SQueue mainQueue] orSignal:[SSignal single:@true]] startWithNext:^(__unused id next) {
|
||||
_transitionInDisposable = [[[[transitionFromItemView readyForTransitionIn] take:1] timeout:1.0 onQueue:[SQueue mainQueue] orSignal:[SSignal single:@true]] startStrictWithNext:^(__unused id next) {
|
||||
__strong TGModernGalleryController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil) {
|
||||
[strongSelf animateTransitionInFromView:transitionInFromView toView:transitionInToView toViewContentRect:transitionInToViewContentRect];
|
||||
@ -674,7 +674,7 @@ static void adjustFrameRate(CAAnimation *animation) {
|
||||
strongSelf->_startedTransitionIn();
|
||||
}
|
||||
}
|
||||
}];
|
||||
} file:__FILE_NAME__ line:__LINE__];
|
||||
} else {
|
||||
if (_startedTransitionIn) {
|
||||
_startedTransitionIn();
|
||||
|
@ -304,7 +304,7 @@
|
||||
{
|
||||
__weak TGNavigationController *weakSelf = self;
|
||||
[_playerStatusDisposable dispose];
|
||||
_playerStatusDisposable = [[[TGNavigationBar musicPlayerProvider].musicPlayerIsActive deliverOn:[SQueue mainQueue]] startWithNext:^(NSNumber *nIsActive)
|
||||
_playerStatusDisposable = [[[TGNavigationBar musicPlayerProvider].musicPlayerIsActive deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSNumber *nIsActive)
|
||||
{
|
||||
__strong TGNavigationController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
@ -327,7 +327,7 @@
|
||||
}];
|
||||
}
|
||||
}
|
||||
}];
|
||||
} file:__FILE_NAME__ line:__LINE__];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -68,7 +68,7 @@
|
||||
__weak TGPassportScanView *weakSelf = self;
|
||||
[_camera captureNextFrameCompletion:^(UIImage *image)
|
||||
{
|
||||
[_ocrDisposable setDisposable:[[[TGPassportOCR recognizeDataInImage:image shouldBeDriversLicense:false] deliverOn:[SQueue mainQueue]] startWithNext:^(TGPassportMRZ *next)
|
||||
[_ocrDisposable setDisposable:[[[TGPassportOCR recognizeDataInImage:image shouldBeDriversLicense:false] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(TGPassportMRZ *next)
|
||||
{
|
||||
__strong TGPassportScanView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -85,7 +85,7 @@
|
||||
{
|
||||
strongSelf->_timer = [TGTimerTarget scheduledMainThreadTimerWithTarget:self action:@selector(handleNextFrame) interval:0.45 repeat:false];
|
||||
}
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -539,8 +539,7 @@ const CGFloat TGPhotoCropViewOverscreenSize = 1000;
|
||||
|
||||
__weak TGPhotoCropView *weakSelf = self;
|
||||
|
||||
_confirmTimer = [[STimer alloc] initWithTimeout:1.0f repeat:false completion:^
|
||||
{
|
||||
_confirmTimer = [[STimer alloc] initWithTimeout:1.0f repeat:false completion:^(__unused STimer *timer) {
|
||||
__strong TGPhotoCropView *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
@ -2618,7 +2618,7 @@
|
||||
[_faceDetectorDisposable setDisposable:[[[cachedSignal catch:^SSignal *(__unused id error)
|
||||
{
|
||||
return detectSignal;
|
||||
}] deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *next)
|
||||
}] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSArray *next)
|
||||
{
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -2630,7 +2630,7 @@
|
||||
return;
|
||||
|
||||
strongSelf->_faces = next;
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
+ (TGPhotoEditorTab)defaultTabsForAvatarIntent:(bool)hasStickers
|
||||
@ -3014,7 +3014,7 @@
|
||||
} else {
|
||||
return images;
|
||||
}
|
||||
}] deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *images)
|
||||
}] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSArray *images)
|
||||
{
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -3039,7 +3039,7 @@
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
strongSelf->_requestingThumbnails = false;
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (void)videoScrubberDidFinishRequestingThumbnails:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber
|
||||
|
@ -217,7 +217,7 @@
|
||||
- (void)setHistogramSignal:(SSignal *)signal
|
||||
{
|
||||
__weak TGPhotoEditorCurvesHistogramView *weakSelf = self;
|
||||
[_histogramDisposable setDisposable:[[signal deliverOn:[SQueue mainQueue]] startWithNext:^(PGPhotoHistogram *next)
|
||||
[_histogramDisposable setDisposable:[[signal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(PGPhotoHistogram *next)
|
||||
{
|
||||
__strong TGPhotoEditorCurvesHistogramView *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
@ -225,7 +225,7 @@
|
||||
strongSelf->_histogram = next;
|
||||
[strongSelf updateHistogram];
|
||||
}
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
@synthesize interactionBegan;
|
||||
|
@ -708,7 +708,7 @@ const NSTimeInterval TGPhotoQualityPreviewDuration = 15.0f;
|
||||
}];
|
||||
}
|
||||
|
||||
[_disposable setDisposable:[[urlSignal deliverOn:[SQueue mainQueue]] startWithNext:^(id next)
|
||||
[_disposable setDisposable:[[urlSignal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id next)
|
||||
{
|
||||
__strong TGPhotoQualityController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -781,7 +781,7 @@ const NSTimeInterval TGPhotoQualityPreviewDuration = 15.0f;
|
||||
}
|
||||
} error:^(id error) {
|
||||
TGLegacyLog(@"Video Quality Preview Error: %@", error);
|
||||
} completed:nil]];
|
||||
} completed:nil file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (void)_setupPlaybackReachedEndObserver
|
||||
|
@ -1293,12 +1293,12 @@ typedef enum
|
||||
- (void)capturePipelineRecordingDidStart:(TGVideoCameraPipeline *)__unused capturePipeline
|
||||
{
|
||||
__weak TGVideoMessageCaptureController *weakSelf = self;
|
||||
[_activityDisposable setDisposable:[[[SSignal complete] delay:0.3 onQueue:[SQueue mainQueue]] startWithNext:nil error:nil completed:^{
|
||||
[_activityDisposable setDisposable:[[[SSignal complete] delay:0.3 onQueue:[SQueue mainQueue]] startStrictWithNext:nil error:nil completed:^{
|
||||
__strong TGVideoMessageCaptureController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil && strongSelf->_requestActivityHolder) {
|
||||
strongSelf->_activityHolder = strongSelf->_requestActivityHolder();
|
||||
}
|
||||
}]];
|
||||
} file:__FILE_NAME__ line:__LINE__]];
|
||||
}
|
||||
|
||||
- (void)capturePipelineRecordingWillStop:(TGVideoCameraPipeline *)__unused capturePipeline
|
||||
|
@ -404,7 +404,7 @@ static CGRect viewFrame(UIView *view)
|
||||
[self addSubview:_slowmodeView];
|
||||
|
||||
__weak TGVideoMessageControls *weakSelf = self;
|
||||
_slowmodeTimer = [[STimer alloc] initWithTimeout:0.5 repeat:true completion:^{
|
||||
_slowmodeTimer = [[STimer alloc] initWithTimeout:0.5 repeat:true completion:^(__unused STimer *timer) {
|
||||
__strong TGVideoMessageControls *strongSelf = weakSelf;
|
||||
if (strongSelf != nil) {
|
||||
int32_t timestamp = (int32_t)[[NSDate date] timeIntervalSince1970];
|
||||
|
@ -395,7 +395,7 @@ static id<LegacyComponentsContext> _defaultContext = nil;
|
||||
_currentSizeClass = UIUserInterfaceSizeClassCompact;
|
||||
|
||||
__weak TGViewController *weakSelf = self;
|
||||
_sizeClassDisposable = [[_context sizeClassSignal] startWithNext:^(NSNumber *next) {
|
||||
_sizeClassDisposable = [[_context sizeClassSignal] startStrictWithNext:^(NSNumber *next) {
|
||||
__strong TGViewController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil) {
|
||||
if (strongSelf->_currentSizeClass != [next integerValue]) {
|
||||
@ -405,7 +405,7 @@ static id<LegacyComponentsContext> _defaultContext = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
} file:__FILE_NAME__ line:__LINE__];
|
||||
initializedSizeClass = true;
|
||||
|
||||
if ([self respondsToSelector:@selector(setAutomaticallyAdjustsScrollViewInsets:)])
|
||||
|
@ -51,12 +51,3 @@
|
||||
- (MTSignal *)reduceLeft:(id)value with:(id (^)(id, id))f;
|
||||
|
||||
@end
|
||||
|
||||
@interface MTPipe : NSObject
|
||||
|
||||
@property (nonatomic, copy, readonly) MTSignal *(^signalProducer)();
|
||||
@property (nonatomic, copy, readonly) void (^sink)(id);
|
||||
|
||||
- (instancetype)initWithReplay:(bool)replay;
|
||||
|
||||
@end
|
||||
|
@ -839,101 +839,3 @@ static dispatch_block_t recursiveBlock(void (^block)(dispatch_block_t recurse))
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface MTPipeReplayState : NSObject
|
||||
|
||||
@property (nonatomic, readonly) bool hasReceivedValue;
|
||||
@property (nonatomic, strong, readonly) id recentValue;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTPipeReplayState
|
||||
|
||||
- (instancetype)initWithReceivedValue:(bool)receivedValue recentValue:(id)recentValue
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
_hasReceivedValue = receivedValue;
|
||||
_recentValue = recentValue;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTPipe
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithReplay:false];
|
||||
}
|
||||
|
||||
- (instancetype)initWithReplay:(bool)replay
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
MTAtomic *subscribers = [[MTAtomic alloc] initWithValue:[[MTBag alloc] init]];
|
||||
MTAtomic *replayState = replay ? [[MTAtomic alloc] initWithValue:[[MTPipeReplayState alloc] initWithReceivedValue:false recentValue:nil]] : nil;
|
||||
|
||||
_signalProducer = [^MTSignal *
|
||||
{
|
||||
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber)
|
||||
{
|
||||
__block NSUInteger index = 0;
|
||||
[subscribers with:^id(MTBag *bag)
|
||||
{
|
||||
index = [bag addItem:[^(id next)
|
||||
{
|
||||
[subscriber putNext:next];
|
||||
} copy]];
|
||||
return nil;
|
||||
}];
|
||||
|
||||
if (replay)
|
||||
{
|
||||
[replayState with:^id(MTPipeReplayState *state)
|
||||
{
|
||||
if (state.hasReceivedValue)
|
||||
[subscriber putNext:state.recentValue];
|
||||
return nil;
|
||||
}];
|
||||
}
|
||||
|
||||
return [[MTBlockDisposable alloc] initWithBlock:^
|
||||
{
|
||||
[subscribers with:^id(MTBag *bag)
|
||||
{
|
||||
[bag removeItem:index];
|
||||
return nil;
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
} copy];
|
||||
|
||||
_sink = [^(id next)
|
||||
{
|
||||
NSArray *items = [subscribers with:^id(MTBag *bag)
|
||||
{
|
||||
return [bag copyItems];
|
||||
}];
|
||||
|
||||
for (void (^item)(id) in items)
|
||||
{
|
||||
item(next);
|
||||
}
|
||||
|
||||
if (replay)
|
||||
{
|
||||
[replayState modify:^id(__unused MTPipeReplayState *state)
|
||||
{
|
||||
return [[MTPipeReplayState alloc] initWithReceivedValue:true recentValue:next];
|
||||
}];
|
||||
}
|
||||
} copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -184,7 +184,7 @@ typedef enum {
|
||||
|
||||
_alternativeLocalization = [[SVariable alloc] init];
|
||||
|
||||
_localizationsDisposable = [[suggestedLocalizationSignal deliverOn:[SQueue mainQueue]] startWithNext:^(TGSuggestedLocalization *next) {
|
||||
_localizationsDisposable = [[suggestedLocalizationSignal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(TGSuggestedLocalization *next) {
|
||||
__strong RMIntroViewController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil && next != nil) {
|
||||
if (strongSelf->_alternativeLocalizationInfo == nil) {
|
||||
@ -203,7 +203,7 @@ typedef enum {
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
} file:__FILE_NAME__ line:__LINE__];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -15,6 +15,9 @@ objc_library(
|
||||
includes = [
|
||||
"Source",
|
||||
],
|
||||
deps = [
|
||||
"//submodules/SSignalKit/SwiftSignalKit"
|
||||
],
|
||||
sdk_frameworks = [
|
||||
"Foundation",
|
||||
],
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
#import <os/lock.h>
|
||||
#import <objc/runtime.h>
|
||||
#import <libkern/OSAtomic.h>
|
||||
#import <pthread/pthread.h>
|
||||
|
||||
@interface SBlockDisposable ()
|
||||
{
|
||||
void *_block;
|
||||
@interface SBlockDisposable () {
|
||||
void (^_action)();
|
||||
pthread_mutex_t _lock;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -18,47 +18,35 @@
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
_block = (__bridge_retained void *)[block copy];
|
||||
_action = [block copy];
|
||||
pthread_mutex_init(&_lock, nil);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
void *block = _block;
|
||||
if (block != NULL)
|
||||
{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
|
||||
{
|
||||
if (block != nil)
|
||||
{
|
||||
__unused __strong id strongBlock = (__bridge_transfer id)block;
|
||||
strongBlock = nil;
|
||||
}
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
- (void)dealloc {
|
||||
void (^freeAction)() = nil;
|
||||
pthread_mutex_lock(&_lock);
|
||||
freeAction = _action;
|
||||
_action = nil;
|
||||
pthread_mutex_unlock(&_lock);
|
||||
|
||||
if (freeAction) {
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&_lock);
|
||||
}
|
||||
|
||||
- (void)dispose
|
||||
{
|
||||
void *block = _block;
|
||||
if (block != NULL)
|
||||
{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
|
||||
{
|
||||
if (block != nil)
|
||||
{
|
||||
__strong id strongBlock = (__bridge_transfer id)block;
|
||||
((dispatch_block_t)strongBlock)();
|
||||
strongBlock = nil;
|
||||
}
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
- (void)dispose {
|
||||
void (^disposeAction)() = nil;
|
||||
|
||||
pthread_mutex_lock(&_lock);
|
||||
disposeAction = _action;
|
||||
_action = nil;
|
||||
pthread_mutex_unlock(&_lock);
|
||||
|
||||
if (disposeAction) {
|
||||
disposeAction();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,91 +2,79 @@
|
||||
|
||||
#import "SSignal.h"
|
||||
|
||||
#import <os/lock.h>
|
||||
#import <pthread/pthread.h>
|
||||
|
||||
@interface SDisposableSet ()
|
||||
{
|
||||
os_unfair_lock _lock;
|
||||
pthread_mutex_t _lock;
|
||||
bool _disposed;
|
||||
id<SDisposable> _singleDisposable;
|
||||
NSArray *_multipleDisposables;
|
||||
NSMutableArray<id<SDisposable>> *_disposables;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDisposableSet
|
||||
|
||||
- (void)add:(id<SDisposable>)disposable
|
||||
{
|
||||
if (disposable == nil)
|
||||
return;
|
||||
|
||||
bool dispose = false;
|
||||
|
||||
os_unfair_lock_lock(&_lock);
|
||||
dispose = _disposed;
|
||||
if (!dispose)
|
||||
{
|
||||
if (_multipleDisposables != nil)
|
||||
{
|
||||
NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithArray:_multipleDisposables];
|
||||
[multipleDisposables addObject:disposable];
|
||||
_multipleDisposables = multipleDisposables;
|
||||
}
|
||||
else if (_singleDisposable != nil)
|
||||
{
|
||||
NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithObjects:_singleDisposable, disposable, nil];
|
||||
_multipleDisposables = multipleDisposables;
|
||||
_singleDisposable = nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
_singleDisposable = disposable;
|
||||
}
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
pthread_mutex_init(&_lock, nil);
|
||||
_disposables = [[NSMutableArray alloc] init];
|
||||
}
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
NSArray<id<SDisposable>> *disposables = nil;
|
||||
pthread_mutex_lock(&_lock);
|
||||
disposables = _disposables;
|
||||
_disposables = nil;
|
||||
pthread_mutex_unlock(&_lock);
|
||||
|
||||
if (dispose)
|
||||
if (disposables) {
|
||||
}
|
||||
pthread_mutex_destroy(&_lock);
|
||||
}
|
||||
|
||||
- (void)add:(id<SDisposable>)disposable {
|
||||
bool disposeImmediately = false;
|
||||
|
||||
pthread_mutex_lock(&_lock);
|
||||
if (_disposed) {
|
||||
disposeImmediately = true;
|
||||
} else {
|
||||
[_disposables addObject:disposable];
|
||||
}
|
||||
pthread_mutex_unlock(&_lock);
|
||||
|
||||
if (disposeImmediately) {
|
||||
[disposable dispose];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)remove:(id<SDisposable>)disposable {
|
||||
os_unfair_lock_lock(&_lock);
|
||||
if (_multipleDisposables != nil)
|
||||
{
|
||||
NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithArray:_multipleDisposables];
|
||||
[multipleDisposables removeObject:disposable];
|
||||
_multipleDisposables = multipleDisposables;
|
||||
pthread_mutex_lock(&_lock);
|
||||
for (NSInteger i = 0; i < _disposables.count; i++) {
|
||||
if (_disposables[i] == disposable) {
|
||||
[_disposables removeObjectAtIndex:i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (_singleDisposable == disposable)
|
||||
{
|
||||
_singleDisposable = nil;
|
||||
}
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
pthread_mutex_unlock(&_lock);
|
||||
}
|
||||
|
||||
- (void)dispose
|
||||
{
|
||||
id<SDisposable> singleDisposable = nil;
|
||||
NSArray *multipleDisposables = nil;
|
||||
|
||||
os_unfair_lock_lock(&_lock);
|
||||
if (!_disposed)
|
||||
{
|
||||
- (void)dispose {
|
||||
NSArray<id<SDisposable>> *disposables = nil;
|
||||
pthread_mutex_lock(&_lock);
|
||||
if (!_disposed) {
|
||||
_disposed = true;
|
||||
singleDisposable = _singleDisposable;
|
||||
multipleDisposables = _multipleDisposables;
|
||||
_singleDisposable = nil;
|
||||
_multipleDisposables = nil;
|
||||
disposables = _disposables;
|
||||
_disposables = nil;
|
||||
}
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
pthread_mutex_unlock(&_lock);
|
||||
|
||||
if (singleDisposable != nil)
|
||||
[singleDisposable dispose];
|
||||
if (multipleDisposables != nil)
|
||||
{
|
||||
for (id<SDisposable> disposable in multipleDisposables)
|
||||
{
|
||||
if (disposables) {
|
||||
for (id<SDisposable> disposable in disposables) {
|
||||
[disposable dispose];
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
#import "SMetaDisposable.h"
|
||||
|
||||
#import <os/lock.h>
|
||||
#import <pthread/pthread.h>
|
||||
|
||||
@interface SMetaDisposable ()
|
||||
{
|
||||
os_unfair_lock _lock;
|
||||
pthread_mutex_t _lock;
|
||||
bool _disposed;
|
||||
id<SDisposable> _disposable;
|
||||
}
|
||||
@ -13,41 +13,64 @@
|
||||
|
||||
@implementation SMetaDisposable
|
||||
|
||||
- (void)setDisposable:(id<SDisposable>)disposable
|
||||
{
|
||||
id<SDisposable> previousDisposable = nil;
|
||||
bool dispose = false;
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
pthread_mutex_init(&_lock, nil);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
id<SDisposable> freeDisposable = nil;
|
||||
pthread_mutex_lock(&_lock);
|
||||
if (_disposable) {
|
||||
freeDisposable = _disposable;
|
||||
_disposable = nil;
|
||||
}
|
||||
pthread_mutex_unlock(&_lock);
|
||||
|
||||
os_unfair_lock_lock(&_lock);
|
||||
dispose = _disposed;
|
||||
if (!dispose)
|
||||
{
|
||||
if (freeDisposable) {
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&_lock);
|
||||
}
|
||||
|
||||
- (void)setDisposable:(id<SDisposable>)disposable {
|
||||
id<SDisposable> previousDisposable = nil;
|
||||
bool disposeImmediately = false;
|
||||
|
||||
pthread_mutex_lock(&_lock);
|
||||
disposeImmediately = _disposed;
|
||||
if (!disposeImmediately) {
|
||||
previousDisposable = _disposable;
|
||||
_disposable = disposable;
|
||||
}
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
pthread_mutex_unlock(&_lock);
|
||||
|
||||
if (previousDisposable != nil)
|
||||
if (previousDisposable) {
|
||||
[previousDisposable dispose];
|
||||
}
|
||||
|
||||
if (dispose)
|
||||
if (disposeImmediately) {
|
||||
[disposable dispose];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dispose
|
||||
{
|
||||
- (void)dispose {
|
||||
id<SDisposable> disposable = nil;
|
||||
|
||||
os_unfair_lock_lock(&_lock);
|
||||
if (!_disposed)
|
||||
{
|
||||
disposable = _disposable;
|
||||
pthread_mutex_lock(&_lock);
|
||||
if (!_disposed) {
|
||||
_disposed = true;
|
||||
disposable = _disposable;
|
||||
_disposable = nil;
|
||||
}
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
pthread_mutex_unlock(&_lock);
|
||||
|
||||
if (disposable != nil)
|
||||
if (disposable) {
|
||||
[disposable dispose];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -1,11 +0,0 @@
|
||||
#import <SSignalKit/SSignal.h>
|
||||
|
||||
@interface SMulticastSignalManager : NSObject
|
||||
|
||||
- (SSignal * _Nonnull)multicastedSignalForKey:(NSString * _Nonnull)key producer:(SSignal * _Nonnull (^ _Nonnull)())producer;
|
||||
- (void)startStandaloneSignalIfNotRunningForKey:(NSString * _Nonnull)key producer:(SSignal * _Nonnull (^ _Nonnull)())producer;
|
||||
|
||||
- (SSignal * _Nonnull)multicastedPipeForKey:(NSString * _Nonnull)key;
|
||||
- (void)putNext:(id _Nullable)next toMulticastedPipeForKey:(NSString * _Nonnull)key;
|
||||
|
||||
@end
|
@ -1,171 +0,0 @@
|
||||
#import "SMulticastSignalManager.h"
|
||||
|
||||
#import "SSignal+Multicast.h"
|
||||
#import "SSignal+SideEffects.h"
|
||||
#import "SBag.h"
|
||||
#import "SMetaDisposable.h"
|
||||
#import "SBlockDisposable.h"
|
||||
|
||||
#import <os/lock.h>
|
||||
|
||||
@interface SMulticastSignalManager ()
|
||||
{
|
||||
os_unfair_lock _lock;
|
||||
NSMutableDictionary *_multicastSignals;
|
||||
NSMutableDictionary *_standaloneSignalDisposables;
|
||||
NSMutableDictionary *_pipeListeners;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SMulticastSignalManager
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
_multicastSignals = [[NSMutableDictionary alloc] init];
|
||||
_standaloneSignalDisposables = [[NSMutableDictionary alloc] init];
|
||||
_pipeListeners = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
NSArray *disposables = nil;
|
||||
os_unfair_lock_lock(&_lock);
|
||||
disposables = [_standaloneSignalDisposables allValues];
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
|
||||
for (id<SDisposable> disposable in disposables)
|
||||
{
|
||||
[disposable dispose];
|
||||
}
|
||||
}
|
||||
|
||||
- (SSignal *)multicastedSignalForKey:(NSString *)key producer:(SSignal *(^)())producer
|
||||
{
|
||||
if (key == nil)
|
||||
{
|
||||
if (producer)
|
||||
return producer();
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
SSignal *signal = nil;
|
||||
os_unfair_lock_lock(&_lock);
|
||||
signal = _multicastSignals[key];
|
||||
if (signal == nil)
|
||||
{
|
||||
__weak SMulticastSignalManager *weakSelf = self;
|
||||
if (producer)
|
||||
signal = producer();
|
||||
if (signal != nil)
|
||||
{
|
||||
signal = [[signal onDispose:^
|
||||
{
|
||||
__strong SMulticastSignalManager *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
{
|
||||
os_unfair_lock_lock(&strongSelf->_lock);
|
||||
[strongSelf->_multicastSignals removeObjectForKey:key];
|
||||
os_unfair_lock_unlock(&strongSelf->_lock);
|
||||
}
|
||||
}] multicast];
|
||||
_multicastSignals[key] = signal;
|
||||
}
|
||||
}
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
- (void)startStandaloneSignalIfNotRunningForKey:(NSString *)key producer:(SSignal *(^)())producer
|
||||
{
|
||||
if (key == nil)
|
||||
return;
|
||||
|
||||
bool produce = false;
|
||||
os_unfair_lock_lock(&_lock);
|
||||
if (_standaloneSignalDisposables[key] == nil)
|
||||
{
|
||||
_standaloneSignalDisposables[key] = [[SMetaDisposable alloc] init];
|
||||
produce = true;
|
||||
}
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
|
||||
if (produce)
|
||||
{
|
||||
__weak SMulticastSignalManager *weakSelf = self;
|
||||
id<SDisposable> disposable = [producer() startWithNext:nil error:^(__unused id error)
|
||||
{
|
||||
__strong SMulticastSignalManager *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
{
|
||||
os_unfair_lock_lock(&strongSelf->_lock);
|
||||
[strongSelf->_standaloneSignalDisposables removeObjectForKey:key];
|
||||
os_unfair_lock_unlock(&strongSelf->_lock);
|
||||
}
|
||||
} completed:^
|
||||
{
|
||||
__strong SMulticastSignalManager *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
{
|
||||
os_unfair_lock_lock(&strongSelf->_lock);
|
||||
[strongSelf->_standaloneSignalDisposables removeObjectForKey:key];
|
||||
os_unfair_lock_unlock(&strongSelf->_lock);
|
||||
}
|
||||
}];
|
||||
|
||||
os_unfair_lock_lock(&_lock);
|
||||
[(SMetaDisposable *)_standaloneSignalDisposables[key] setDisposable:disposable];
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
}
|
||||
}
|
||||
|
||||
- (SSignal *)multicastedPipeForKey:(NSString *)key
|
||||
{
|
||||
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
|
||||
{
|
||||
os_unfair_lock_lock(&_lock);
|
||||
SBag *bag = _pipeListeners[key];
|
||||
if (bag == nil)
|
||||
{
|
||||
bag = [[SBag alloc] init];
|
||||
_pipeListeners[key] = bag;
|
||||
}
|
||||
NSInteger index = [bag addItem:[^(id next)
|
||||
{
|
||||
[subscriber putNext:next];
|
||||
} copy]];
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
|
||||
return [[SBlockDisposable alloc] initWithBlock:^
|
||||
{
|
||||
os_unfair_lock_lock(&_lock);
|
||||
SBag *bag = _pipeListeners[key];
|
||||
[bag removeItem:index];
|
||||
if ([bag isEmpty]) {
|
||||
[_pipeListeners removeObjectForKey:key];
|
||||
}
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)putNext:(id)next toMulticastedPipeForKey:(NSString *)key
|
||||
{
|
||||
os_unfair_lock_lock(&_lock);
|
||||
NSArray *pipeListeners = [(SBag *)_pipeListeners[key] copyItems];
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
|
||||
for (void (^listener)(id) in pipeListeners)
|
||||
{
|
||||
listener(next);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@ -1,8 +0,0 @@
|
||||
#import <SSignalKit/SSignal.h>
|
||||
|
||||
@interface SSignal (Accumulate)
|
||||
|
||||
- (SSignal * _Nonnull)reduceLeft:(id _Nullable)value with:(id _Nullable (^ _Nonnull)(id _Nullable, id _Nullable))f;
|
||||
- (SSignal * _Nonnull)reduceLeftWithPassthrough:(id _Nullable)value with:(id _Nullable (^ _Nonnull)(id _Nullable, id _Nullable, void (^ _Nonnull)(id _Nullable)))f;
|
||||
|
||||
@end
|
@ -1,52 +0,0 @@
|
||||
#import "SSignal+Accumulate.h"
|
||||
|
||||
@implementation SSignal (Accumulate)
|
||||
|
||||
- (SSignal *)reduceLeft:(id)value with:(id (^)(id, id))f
|
||||
{
|
||||
return [[SSignal alloc] initWithGenerator:^(SSubscriber *subscriber)
|
||||
{
|
||||
__block id intermediateResult = value;
|
||||
|
||||
return [self startWithNext:^(id next)
|
||||
{
|
||||
intermediateResult = f(intermediateResult, next);
|
||||
} error:^(id error)
|
||||
{
|
||||
[subscriber putError:error];
|
||||
} completed:^
|
||||
{
|
||||
if (intermediateResult != nil)
|
||||
[subscriber putNext:intermediateResult];
|
||||
[subscriber putCompletion];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (SSignal *)reduceLeftWithPassthrough:(id)value with:(id (^)(id, id, void (^)(id)))f
|
||||
{
|
||||
return [[SSignal alloc] initWithGenerator:^(SSubscriber *subscriber)
|
||||
{
|
||||
__block id intermediateResult = value;
|
||||
|
||||
void (^emit)(id) = ^(id next)
|
||||
{
|
||||
[subscriber putNext:next];
|
||||
};
|
||||
|
||||
return [self startWithNext:^(id next)
|
||||
{
|
||||
intermediateResult = f(intermediateResult, next, emit);
|
||||
} error:^(id error)
|
||||
{
|
||||
[subscriber putError:error];
|
||||
} completed:^
|
||||
{
|
||||
if (intermediateResult != nil)
|
||||
[subscriber putNext:intermediateResult];
|
||||
[subscriber putCompletion];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
@ -157,7 +157,7 @@
|
||||
{
|
||||
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) {
|
||||
SAtomic *value = [[SAtomic alloc] initWithValue:nil];
|
||||
STimer *timer = [[STimer alloc] initWithTimeout:delay repeat:false completion:^{
|
||||
STimer *timer = [[STimer alloc] initWithTimeout:delay repeat:false completion:^(__unused STimer *timer) {
|
||||
[value modify:^id(SSignal_ThrottleContainer *container) {
|
||||
if (container != nil) {
|
||||
if (!container.committed) {
|
||||
|
@ -1,7 +0,0 @@
|
||||
#import <SSignalKit/SSignal.h>
|
||||
|
||||
@interface SSignal (Multicast)
|
||||
|
||||
- (SSignal * _Nonnull)multicast;
|
||||
|
||||
@end
|
@ -1,158 +0,0 @@
|
||||
#import "SSignal+Multicast.h"
|
||||
|
||||
#import <os/lock.h>
|
||||
#import "SBag.h"
|
||||
#import "SBlockDisposable.h"
|
||||
|
||||
typedef enum {
|
||||
SSignalMulticastStateReady,
|
||||
SSignalMulticastStateStarted,
|
||||
SSignalMulticastStateCompleted
|
||||
} SSignalMulticastState;
|
||||
|
||||
@interface SSignalMulticastSubscribers : NSObject
|
||||
{
|
||||
os_unfair_lock _lock;
|
||||
SBag *_subscribers;
|
||||
SSignalMulticastState _state;
|
||||
id<SDisposable> _disposable;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SSignalMulticastSubscribers
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
_subscribers = [[SBag alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setDisposable:(id<SDisposable>)disposable
|
||||
{
|
||||
[_disposable dispose];
|
||||
_disposable = disposable;
|
||||
}
|
||||
|
||||
- (id<SDisposable>)addSubscriber:(SSubscriber *)subscriber start:(bool *)start
|
||||
{
|
||||
os_unfair_lock_lock(&_lock);
|
||||
NSInteger index = [_subscribers addItem:subscriber];
|
||||
switch (_state) {
|
||||
case SSignalMulticastStateReady:
|
||||
*start = true;
|
||||
_state = SSignalMulticastStateStarted;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
|
||||
return [[SBlockDisposable alloc] initWithBlock:^
|
||||
{
|
||||
[self remove:index];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)remove:(NSInteger)index
|
||||
{
|
||||
id<SDisposable> currentDisposable = nil;
|
||||
|
||||
os_unfair_lock_lock(&_lock);
|
||||
[_subscribers removeItem:index];
|
||||
switch (_state) {
|
||||
case SSignalMulticastStateStarted:
|
||||
if ([_subscribers isEmpty])
|
||||
{
|
||||
currentDisposable = _disposable;
|
||||
_disposable = nil;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
|
||||
[currentDisposable dispose];
|
||||
}
|
||||
|
||||
- (void)notifyNext:(id)next
|
||||
{
|
||||
NSArray *currentSubscribers = nil;
|
||||
os_unfair_lock_lock(&_lock);
|
||||
currentSubscribers = [_subscribers copyItems];
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
|
||||
for (SSubscriber *subscriber in currentSubscribers)
|
||||
{
|
||||
[subscriber putNext:next];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)notifyError:(id)error
|
||||
{
|
||||
NSArray *currentSubscribers = nil;
|
||||
os_unfair_lock_lock(&_lock);
|
||||
currentSubscribers = [_subscribers copyItems];
|
||||
_state = SSignalMulticastStateCompleted;
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
|
||||
for (SSubscriber *subscriber in currentSubscribers)
|
||||
{
|
||||
[subscriber putError:error];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)notifyCompleted
|
||||
{
|
||||
NSArray *currentSubscribers = nil;
|
||||
os_unfair_lock_lock(&_lock);
|
||||
currentSubscribers = [_subscribers copyItems];
|
||||
_state = SSignalMulticastStateCompleted;
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
|
||||
for (SSubscriber *subscriber in currentSubscribers)
|
||||
{
|
||||
[subscriber putCompletion];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SSignal (Multicast)
|
||||
|
||||
- (SSignal *)multicast
|
||||
{
|
||||
SSignalMulticastSubscribers *subscribers = [[SSignalMulticastSubscribers alloc] init];
|
||||
return [[SSignal alloc] initWithGenerator:^id<SDisposable> (SSubscriber *subscriber)
|
||||
{
|
||||
bool start = false;
|
||||
id<SDisposable> currentDisposable = [subscribers addSubscriber:subscriber start:&start];
|
||||
if (start)
|
||||
{
|
||||
id<SDisposable> disposable = [self startWithNext:^(id next)
|
||||
{
|
||||
[subscribers notifyNext:next];
|
||||
} error:^(id error)
|
||||
{
|
||||
[subscribers notifyError:error];
|
||||
} completed:^
|
||||
{
|
||||
[subscribers notifyCompleted];
|
||||
}];
|
||||
|
||||
[subscribers setDisposable:[[SBlockDisposable alloc] initWithBlock:^
|
||||
{
|
||||
[disposable dispose];
|
||||
}]];
|
||||
}
|
||||
|
||||
return currentDisposable;
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
@ -14,11 +14,11 @@
|
||||
{
|
||||
return [[SSignal alloc] initWithGenerator:^id<SDisposable> (SSubscriber *subscriber)
|
||||
{
|
||||
SMetaDisposable *disposable = [[SMetaDisposable alloc] init];
|
||||
SMetaDisposable *startDisposable = [[SMetaDisposable alloc] init];
|
||||
SMetaDisposable *timerDisposable = [[SMetaDisposable alloc] init];
|
||||
|
||||
STimer *timer = [[STimer alloc] initWithTimeout:seconds repeat:false completion:^
|
||||
{
|
||||
[disposable setDisposable:[self startWithNext:^(id next)
|
||||
STimer *timer = [[STimer alloc] initWithTimeout:seconds repeat:false completion:^(__unused STimer *timer) {
|
||||
[startDisposable setDisposable:[self startWithNext:^(id next)
|
||||
{
|
||||
[subscriber putNext:next];
|
||||
} error:^(id error)
|
||||
@ -32,12 +32,15 @@
|
||||
|
||||
[timer start];
|
||||
|
||||
[disposable setDisposable:[[SBlockDisposable alloc] initWithBlock:^
|
||||
[timerDisposable setDisposable:[[SBlockDisposable alloc] initWithBlock:^
|
||||
{
|
||||
[timer invalidate];
|
||||
}]];
|
||||
|
||||
return disposable;
|
||||
return [[SBlockDisposable alloc] initWithBlock:^{
|
||||
[startDisposable dispose];
|
||||
[timerDisposable dispose];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
@ -45,11 +48,12 @@
|
||||
{
|
||||
return [[SSignal alloc] initWithGenerator:^id<SDisposable> (SSubscriber *subscriber)
|
||||
{
|
||||
SMetaDisposable *disposable = [[SMetaDisposable alloc] init];
|
||||
SMetaDisposable *startDisposable = [[SMetaDisposable alloc] init];
|
||||
SMetaDisposable *timerDisposable = [[SMetaDisposable alloc] init];
|
||||
|
||||
STimer *timer = [[STimer alloc] initWithTimeout:seconds repeat:false completion:^
|
||||
STimer *timer = [[STimer alloc] initWithTimeout:seconds repeat:false completion:^(__unused STimer *timer)
|
||||
{
|
||||
[disposable setDisposable:[signal startWithNext:^(id next)
|
||||
[startDisposable setDisposable:[signal startWithNext:^(id next)
|
||||
{
|
||||
[subscriber putNext:next];
|
||||
} error:^(id error)
|
||||
@ -62,7 +66,7 @@
|
||||
} queue:queue];
|
||||
[timer start];
|
||||
|
||||
[disposable setDisposable:[self startWithNext:^(id next)
|
||||
[timerDisposable setDisposable:[self startWithNext:^(id next)
|
||||
{
|
||||
[timer invalidate];
|
||||
[subscriber putNext:next];
|
||||
@ -76,7 +80,10 @@
|
||||
[subscriber putCompletion];
|
||||
}]];
|
||||
|
||||
return disposable;
|
||||
return [[SBlockDisposable alloc] initWithBlock:^{
|
||||
[startDisposable dispose];
|
||||
[timerDisposable dispose];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,13 @@
|
||||
- (instancetype _Nonnull)initWithGenerator:(id<SDisposable> _Nullable (^ _Nonnull)(SSubscriber * _Nonnull))generator;
|
||||
|
||||
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next error:(void (^ _Nullable)(id _Nullable error))error completed:(void (^ _Nullable)())completed;
|
||||
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next;
|
||||
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next completed:(void (^ _Nullable)())completed;
|
||||
- (id<SDisposable> _Nullable)startStrictWithNext:(void (^ _Nullable)(id _Nullable next))next error:(void (^ _Nullable)(id _Nullable error))error completed:(void (^ _Nullable)())completed file:(const char * _Nonnull)file line:(int)line;
|
||||
|
||||
- (SSignal * _Nonnull)trace:(NSString * _Nonnull)name;
|
||||
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next;
|
||||
- (id<SDisposable> _Nullable)startStrictWithNext:(void (^ _Nullable)(id _Nullable next))next file:(const char * _Nonnull)file line:(int)line;
|
||||
|
||||
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next completed:(void (^ _Nullable)())completed;
|
||||
- (id<SDisposable> _Nullable)startStrictWithNext:(void (^ _Nullable)(id _Nullable next))next completed:(void (^ _Nullable)())completed file:(const char * _Nonnull)file line:(int)line;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -2,30 +2,99 @@
|
||||
|
||||
#import "SBlockDisposable.h"
|
||||
|
||||
#import <pthread/pthread.h>
|
||||
|
||||
@interface SSubscriberDisposable : NSObject <SDisposable>
|
||||
{
|
||||
SSubscriber *_subscriber;
|
||||
__weak SSubscriber *_subscriber;
|
||||
id<SDisposable> _disposable;
|
||||
pthread_mutex_t _lock;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SSubscriberDisposable
|
||||
|
||||
- (instancetype)initWithSubscriber:(SSubscriber *)subscriber disposable:(id<SDisposable>)disposable
|
||||
{
|
||||
- (instancetype)initWithSubscriber:(SSubscriber *)subscriber disposable:(id<SDisposable>)disposable {
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
if (self != nil) {
|
||||
_subscriber = subscriber;
|
||||
_disposable = disposable;
|
||||
pthread_mutex_init(&_lock, nil);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dispose
|
||||
{
|
||||
[_subscriber _markTerminatedWithoutDisposal];
|
||||
- (void)dealloc {
|
||||
pthread_mutex_destroy(&_lock);
|
||||
}
|
||||
|
||||
- (void)dispose {
|
||||
SSubscriber *subscriber = nil;
|
||||
id<SDisposable> disposeItem = nil;
|
||||
pthread_mutex_lock(&_lock);
|
||||
disposeItem = _disposable;
|
||||
_disposable = nil;
|
||||
subscriber = _subscriber;
|
||||
_subscriber = nil;
|
||||
pthread_mutex_unlock(&_lock);
|
||||
|
||||
[disposeItem dispose];
|
||||
[subscriber _markTerminatedWithoutDisposal];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface SStrictDisposable : NSObject<SDisposable> {
|
||||
id<SDisposable> _disposable;
|
||||
const char *_file;
|
||||
int _line;
|
||||
|
||||
#if DEBUG
|
||||
pthread_mutex_t _lock;
|
||||
bool _isDisposed;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (instancetype)initWithDisposable:(id<SDisposable>)disposable file:(const char *)file line:(int)line;
|
||||
- (void)dispose;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SStrictDisposable
|
||||
|
||||
- (instancetype)initWithDisposable:(id<SDisposable>)disposable file:(const char *)file line:(int)line {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_disposable = disposable;
|
||||
_file = file;
|
||||
_line = line;
|
||||
|
||||
#if DEBUG
|
||||
pthread_mutex_init(&_lock, nil);
|
||||
#endif
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
#if DEBUG
|
||||
pthread_mutex_lock(&_lock);
|
||||
if (!_isDisposed) {
|
||||
NSLog(@"Leaked disposable from %s:%d", _file, _line);
|
||||
assert(false);
|
||||
}
|
||||
pthread_mutex_unlock(&_lock);
|
||||
|
||||
pthread_mutex_destroy(&_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)dispose {
|
||||
pthread_mutex_lock(&_lock);
|
||||
_isDisposed = true;
|
||||
pthread_mutex_unlock(&_lock);
|
||||
|
||||
[_disposable dispose];
|
||||
}
|
||||
|
||||
@ -39,69 +108,54 @@
|
||||
|
||||
@implementation SSignal
|
||||
|
||||
- (instancetype)initWithGenerator:(id<SDisposable> (^)(SSubscriber *))generator
|
||||
{
|
||||
- (instancetype)initWithGenerator:(id<SDisposable> (^)(SSubscriber *))generator {
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
if (self != nil) {
|
||||
_generator = [generator copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id<SDisposable>)startWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed traceName:(NSString *)traceName
|
||||
{
|
||||
STracingSubscriber *subscriber = [[STracingSubscriber alloc] initWithName:traceName next:next error:error completed:completed];
|
||||
id<SDisposable> disposable = _generator(subscriber);
|
||||
[subscriber _assignDisposable:disposable];
|
||||
return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
|
||||
}
|
||||
|
||||
- (id<SDisposable>)startWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed
|
||||
{
|
||||
- (id<SDisposable>)startWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed {
|
||||
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:error completed:completed];
|
||||
id<SDisposable> disposable = _generator(subscriber);
|
||||
[subscriber _assignDisposable:disposable];
|
||||
return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
|
||||
}
|
||||
|
||||
- (id<SDisposable>)startWithNext:(void (^)(id next))next
|
||||
{
|
||||
- (id<SDisposable>)startStrictWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed file:(const char * _Nonnull)file line:(int)line {
|
||||
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:error completed:completed];
|
||||
id<SDisposable> disposable = _generator(subscriber);
|
||||
[subscriber _assignDisposable:disposable];
|
||||
return [[SStrictDisposable alloc] initWithDisposable:[[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable] file:file line:line];
|
||||
}
|
||||
|
||||
- (id<SDisposable>)startWithNext:(void (^)(id next))next {
|
||||
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:nil completed:nil];
|
||||
id<SDisposable> disposable = _generator(subscriber);
|
||||
[subscriber _assignDisposable:disposable];
|
||||
return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
|
||||
}
|
||||
|
||||
- (id<SDisposable>)startWithNext:(void (^)(id next))next completed:(void (^)())completed
|
||||
{
|
||||
- (id<SDisposable>)startStrictWithNext:(void (^)(id next))next file:(const char * _Nonnull)file line:(int)line {
|
||||
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:nil completed:nil];
|
||||
id<SDisposable> disposable = _generator(subscriber);
|
||||
[subscriber _assignDisposable:disposable];
|
||||
return [[SStrictDisposable alloc] initWithDisposable:[[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable] file:file line:line];
|
||||
}
|
||||
|
||||
- (id<SDisposable>)startWithNext:(void (^)(id next))next completed:(void (^)())completed {
|
||||
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:nil completed:completed];
|
||||
id<SDisposable> disposable = _generator(subscriber);
|
||||
[subscriber _assignDisposable:disposable];
|
||||
return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
|
||||
}
|
||||
|
||||
- (SSignal *)trace:(NSString *)name
|
||||
{
|
||||
#ifdef DEBUG
|
||||
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
|
||||
{
|
||||
NSString *traceName = [[NSString alloc] initWithFormat:@"%@#0x%x", name, (int)random()];
|
||||
NSLog(@"trace(%@ start)", traceName);
|
||||
return [self startWithNext:^(id next)
|
||||
{
|
||||
[subscriber putNext:next];
|
||||
} error:^(id error)
|
||||
{
|
||||
[subscriber putError:error];
|
||||
} completed:^
|
||||
{
|
||||
[subscriber putCompletion];
|
||||
} traceName:traceName];
|
||||
}];
|
||||
#else
|
||||
return self;
|
||||
#endif
|
||||
- (id<SDisposable>)startStrictWithNext:(void (^)(id next))next completed:(void (^)())completed file:(const char * _Nonnull)file line:(int)line {
|
||||
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:nil completed:completed];
|
||||
id<SDisposable> disposable = _generator(subscriber);
|
||||
[subscriber _assignDisposable:disposable];
|
||||
return [[SStrictDisposable alloc] initWithDisposable:[[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable] file:file line:line];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -22,9 +22,7 @@ FOUNDATION_EXPORT const unsigned char SSignalKitVersionString[];
|
||||
#import <SSignalKit/SMetaDisposable.h>
|
||||
#import <SSignalKit/SSignal+Single.h>
|
||||
#import <SSignalKit/SSignal+Mapping.h>
|
||||
#import <SSignalKit/SSignal+Multicast.h>
|
||||
#import <SSignalKit/SSignal+Meta.h>
|
||||
#import <SSignalKit/SSignal+Accumulate.h>
|
||||
#import <SSignalKit/SSignal+Dispatch.h>
|
||||
#import <SSignalKit/SSignal+Catch.h>
|
||||
#import <SSignalKit/SSignal+SideEffects.h>
|
||||
@ -32,7 +30,6 @@ FOUNDATION_EXPORT const unsigned char SSignalKitVersionString[];
|
||||
#import <SSignalKit/SSignal+Timing.h>
|
||||
#import <SSignalKit/SSignal+Take.h>
|
||||
#import <SSignalKit/SSignal+Pipe.h>
|
||||
#import <SSignalKit/SMulticastSignalManager.h>
|
||||
#import <SSignalKit/STimer.h>
|
||||
#import <SSignalKit/SVariable.h>
|
||||
#import <SSignalKit/SQueueLocalObject.h>
|
||||
|
@ -65,6 +65,7 @@
|
||||
|
||||
- (void)_markTerminatedWithoutDisposal
|
||||
{
|
||||
id<SDisposable> disposable = nil;
|
||||
os_unfair_lock_lock(&_lock);
|
||||
SSubscriberBlocks *blocks = nil;
|
||||
if (!_terminated)
|
||||
@ -74,11 +75,16 @@
|
||||
|
||||
_terminated = true;
|
||||
}
|
||||
disposable = _disposable;
|
||||
_disposable = nil;
|
||||
os_unfair_lock_unlock(&_lock);
|
||||
|
||||
if (blocks) {
|
||||
blocks = nil;
|
||||
}
|
||||
if (disposable) {
|
||||
disposable = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)putNext:(id)next
|
||||
@ -116,8 +122,10 @@
|
||||
blocks->_error(error);
|
||||
}
|
||||
|
||||
if (shouldDispose)
|
||||
if (shouldDispose) {
|
||||
[self->_disposable dispose];
|
||||
self->_disposable = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)putCompletion
|
||||
@ -139,13 +147,16 @@
|
||||
if (blocks && blocks->_completed)
|
||||
blocks->_completed();
|
||||
|
||||
if (shouldDispose)
|
||||
if (shouldDispose) {
|
||||
[self->_disposable dispose];
|
||||
self->_disposable = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dispose
|
||||
{
|
||||
[self->_disposable dispose];
|
||||
self->_disposable = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
@interface STimer : NSObject
|
||||
|
||||
- (instancetype _Nonnull)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(dispatch_block_t _Nonnull)completion queue:(SQueue * _Nonnull)queue;
|
||||
- (instancetype _Nonnull)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(dispatch_block_t _Nonnull)completion nativeQueue:(dispatch_queue_t _Nonnull)nativeQueue;
|
||||
- (instancetype _Nonnull)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(void (^ _Nonnull)(STimer * _Nonnull))completion queue:(SQueue * _Nonnull)queue;
|
||||
- (instancetype _Nonnull)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(void (^ _Nonnull)(STimer * _Nonnull))completion nativeQueue:(dispatch_queue_t _Nonnull)nativeQueue;
|
||||
|
||||
- (void)start;
|
||||
- (void)invalidate;
|
||||
|
@ -8,7 +8,7 @@
|
||||
NSTimeInterval _timeout;
|
||||
NSTimeInterval _timeoutDate;
|
||||
bool _repeat;
|
||||
dispatch_block_t _completion;
|
||||
void (^_completion)(STimer * _Nonnull);
|
||||
dispatch_queue_t _nativeQueue;
|
||||
}
|
||||
|
||||
@ -16,11 +16,11 @@
|
||||
|
||||
@implementation STimer
|
||||
|
||||
- (id)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(dispatch_block_t)completion queue:(SQueue *)queue {
|
||||
- (id)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(void (^ _Nonnull)(STimer * _Nonnull))completion queue:(SQueue *)queue {
|
||||
return [self initWithTimeout:timeout repeat:repeat completion:completion nativeQueue:queue._dispatch_queue];
|
||||
}
|
||||
|
||||
- (id)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(dispatch_block_t)completion nativeQueue:(dispatch_queue_t)nativeQueue
|
||||
- (id)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(void (^ _Nonnull)(STimer * _Nonnull))completion nativeQueue:(dispatch_queue_t)nativeQueue
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
@ -54,7 +54,7 @@
|
||||
dispatch_source_set_event_handler(_timer, ^
|
||||
{
|
||||
if (_completion)
|
||||
_completion();
|
||||
_completion(self);
|
||||
if (!_repeat)
|
||||
[self invalidate];
|
||||
});
|
||||
@ -64,7 +64,7 @@
|
||||
- (void)fireAndInvalidate
|
||||
{
|
||||
if (_completion)
|
||||
_completion();
|
||||
_completion(self);
|
||||
|
||||
[self invalidate];
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
return (views, peers, globalNotificationSettings, allEntityFiles)
|
||||
}
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { [weak self] views, peers, globalNotificationSettings, allEntityFiles in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] views, peers, globalNotificationSettings, allEntityFiles in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -384,7 +384,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
self.nextPeerContext = nextPeerContext
|
||||
|
||||
self.centralDisposable = (centralPeerContext.updated.get()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -393,7 +393,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
|
||||
if let previousPeerContext {
|
||||
self.previousDisposable = (previousPeerContext.updated.get()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -403,7 +403,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
|
||||
if let nextPeerContext {
|
||||
self.nextDisposable = (nextPeerContext.updated.get()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -493,7 +493,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: focusedPeerId)),
|
||||
singlePeerListContext.state
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] peer, state in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] peer, state in
|
||||
guard let self, let peer else {
|
||||
return
|
||||
}
|
||||
@ -587,7 +587,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
})
|
||||
} else {
|
||||
self.storySubscriptionsDisposable = (context.engine.messages.storySubscriptions(isHidden: isHidden, tempKeepNewlyArchived: true)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] storySubscriptions in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] storySubscriptions in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -689,6 +689,8 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
disposable.dispose()
|
||||
}
|
||||
self.storySubscriptionsDisposable?.dispose()
|
||||
self.currentStateUpdatedDisposable?.dispose()
|
||||
self.pendingStateReadyDisposable?.dispose()
|
||||
}
|
||||
|
||||
private func updatePeerContexts() {
|
||||
@ -721,7 +723,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
}
|
||||
}
|
||||
for (peerId, ids) in idsByPeerId {
|
||||
self.requestStoryDisposables.add(self.context.engine.messages.refreshStories(peerId: peerId, ids: ids).start())
|
||||
self.requestStoryDisposables.add(self.context.engine.messages.refreshStories(peerId: peerId, ids: ids).startStrict())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -771,7 +773,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
)
|
||||
self.pendingState = pendingState
|
||||
self.pendingStateReadyDisposable = (pendingState.updated.get()
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak pendingState] _ in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self, weak pendingState] _ in
|
||||
guard let self, let pendingState, self.pendingState === pendingState, pendingState.isReady else {
|
||||
return
|
||||
}
|
||||
@ -785,7 +787,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
|
||||
self.currentStateUpdatedDisposable?.dispose()
|
||||
self.currentStateUpdatedDisposable = (pendingState.updated.get()
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak pendingState] _ in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self, weak pendingState] _ in
|
||||
guard let self, let pendingState, self.currentState === pendingState else {
|
||||
return
|
||||
}
|
||||
@ -864,7 +866,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
for (id, info) in resultResources.sorted(by: { $0.value.priority < $1.value.priority }) {
|
||||
validIds.append(id)
|
||||
if self.preloadStoryResourceDisposables[id] == nil {
|
||||
self.preloadStoryResourceDisposables[id] = preloadStoryMedia(context: context, peer: info.peer, storyId: info.storyId, media: info.media, reactions: info.reactions).start()
|
||||
self.preloadStoryResourceDisposables[id] = preloadStoryMedia(context: context, peer: info.peer, storyId: info.storyId, media: info.media, reactions: info.reactions).startStrict()
|
||||
}
|
||||
}
|
||||
|
||||
@ -890,7 +892,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
for (peerId, ids) in pollIdByPeerId {
|
||||
for id in ids {
|
||||
if self.pollStoryMetadataDisposables[StoryId(peerId: peerId, id: id)] == nil {
|
||||
self.pollStoryMetadataDisposables[StoryId(peerId: peerId, id: id)] = self.context.engine.messages.refreshStoryViews(peerId: peerId, ids: ids).start()
|
||||
self.pollStoryMetadataDisposables[StoryId(peerId: peerId, id: id)] = self.context.engine.messages.refreshStoryViews(peerId: peerId, ids: ids).startStrict()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -953,7 +955,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
|
||||
public func markAsSeen(id: StoryId) {
|
||||
if !self.context.sharedContext.immediateExperimentalUISettings.skipReadHistory {
|
||||
let _ = self.context.engine.messages.markStoryAsSeen(peerId: id.peerId, id: id.id, asPinned: false).start()
|
||||
let _ = self.context.engine.messages.markStoryAsSeen(peerId: id.peerId, id: id.id, asPinned: false).startStandalone()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1038,7 +1040,7 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
|
||||
}
|
||||
}
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] data, itemAndPeers in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] data, itemAndPeers in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -1063,7 +1065,7 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
|
||||
if !self.requestedStoryKeys.contains(storyKey) {
|
||||
self.requestedStoryKeys.insert(storyKey)
|
||||
|
||||
self.requestStoryDisposables.add(self.context.engine.messages.refreshStories(peerId: storyId.peerId, ids: [storyId.id]).start())
|
||||
self.requestStoryDisposables.add(self.context.engine.messages.refreshStories(peerId: storyId.peerId, ids: [storyId.id]).startStrict())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1158,7 +1160,7 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
|
||||
public func markAsSeen(id: StoryId) {
|
||||
if self.readGlobally {
|
||||
if !self.context.sharedContext.immediateExperimentalUISettings.skipReadHistory {
|
||||
let _ = self.context.engine.messages.markStoryAsSeen(peerId: id.peerId, id: id.id, asPinned: false).start()
|
||||
let _ = self.context.engine.messages.markStoryAsSeen(peerId: id.peerId, id: id.id, asPinned: false).startStandalone()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1205,7 +1207,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
||||
listContext.state,
|
||||
self.focusedIdUpdated.get()
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] data, state, _ in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] data, state, _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -1391,7 +1393,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
||||
if let mediaId = info.media.id {
|
||||
validIds.append(mediaId)
|
||||
if self.preloadStoryResourceDisposables[mediaId] == nil {
|
||||
self.preloadStoryResourceDisposables[mediaId] = preloadStoryMedia(context: context, peer: info.peer, storyId: info.storyId, media: info.media, reactions: info.reactions).start()
|
||||
self.preloadStoryResourceDisposables[mediaId] = preloadStoryMedia(context: context, peer: info.peer, storyId: info.storyId, media: info.media, reactions: info.reactions).startStrict()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1416,7 +1418,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
||||
}
|
||||
}
|
||||
for (peerId, ids) in pollIdByPeerId {
|
||||
self.pollStoryMetadataDisposables.add(self.context.engine.messages.refreshStoryViews(peerId: peerId, ids: ids).start())
|
||||
self.pollStoryMetadataDisposables.add(self.context.engine.messages.refreshStoryViews(peerId: peerId, ids: ids).startStrict())
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -1472,7 +1474,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
||||
|
||||
public func markAsSeen(id: StoryId) {
|
||||
if !self.context.sharedContext.immediateExperimentalUISettings.skipReadHistory {
|
||||
let _ = self.context.engine.messages.markStoryAsSeen(peerId: id.peerId, id: id.id, asPinned: true).start()
|
||||
let _ = self.context.engine.messages.markStoryAsSeen(peerId: id.peerId, id: id.id, asPinned: true).startStandalone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -605,7 +605,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
self.addGestureRecognizer(viewListSwipeRecognizer)
|
||||
|
||||
self.audioRecorderDisposable = (self.sendMessageContext.audioRecorder.get()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] audioRecorder in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] audioRecorder in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -624,7 +624,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
audioRecorder.start()
|
||||
self.audioRecorderStatusDisposable = (audioRecorder.recordingState
|
||||
|> deliverOnMainQueue).start(next: { [weak self] value in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] value in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -639,7 +639,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
})
|
||||
|
||||
self.videoRecorderDisposable = (self.sendMessageContext.videoRecorder.get()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] videoRecorder in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] videoRecorder in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -703,6 +703,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
self.audioRecorderDisposable?.dispose()
|
||||
self.audioRecorderStatusDisposable?.dispose()
|
||||
self.audioRecorderStatusDisposable?.dispose()
|
||||
self.videoRecorderDisposable?.dispose()
|
||||
}
|
||||
|
||||
func allowsExternalGestures(point: CGPoint) -> Bool {
|
||||
@ -2473,7 +2474,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
self.updateIsProgressPaused()
|
||||
component.controller()?.present(tooltipScreen, in: .current)
|
||||
|
||||
let _ = ApplicationSpecificNotice.setDisplayStoryReactionTooltip(accountManager: component.context.sharedContext.accountManager).start()
|
||||
let _ = ApplicationSpecificNotice.setDisplayStoryReactionTooltip(accountManager: component.context.sharedContext.accountManager).startStandalone()
|
||||
}
|
||||
|
||||
func saveDraft() {
|
||||
@ -3270,7 +3271,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
TelegramEngine.EngineData.Item.Peer.IsContact(id: peer.id),
|
||||
TelegramEngine.EngineData.Item.Peer.IsBlocked(id: peer.id),
|
||||
TelegramEngine.EngineData.Item.Peer.IsBlockedFromStories(id: peer.id)
|
||||
) |> deliverOnMainQueue).start(next: { [weak self] isContact, maybeIsBlocked, maybeIsBlockedFromStories in
|
||||
) |> deliverOnMainQueue).startStandalone(next: { [weak self] isContact, maybeIsBlocked, maybeIsBlockedFromStories in
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
|
||||
var itemList: [ContextMenuItem] = []
|
||||
|
||||
@ -3289,7 +3290,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}, action: { [weak self] _, f in
|
||||
f(.default)
|
||||
|
||||
let _ = component.blockedPeers?.remove(peerId: peer.id).start()
|
||||
let _ = component.blockedPeers?.remove(peerId: peer.id).startStandalone()
|
||||
|
||||
guard let self else {
|
||||
return
|
||||
@ -3311,7 +3312,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Stories"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] _, f in
|
||||
f(.default)
|
||||
let _ = component.blockedPeers?.add(peerId: peer.id).start()
|
||||
let _ = component.blockedPeers?.add(peerId: peer.id).startStandalone()
|
||||
|
||||
guard let self else {
|
||||
return
|
||||
@ -3335,7 +3336,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}, action: { [weak self] _, f in
|
||||
f(.default)
|
||||
|
||||
let _ = component.context.engine.contacts.deleteContactPeerInteractively(peerId: peer.id).start()
|
||||
let _ = component.context.engine.contacts.deleteContactPeerInteractively(peerId: peer.id).startStandalone()
|
||||
|
||||
guard let self else {
|
||||
return
|
||||
@ -3368,7 +3369,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
return false
|
||||
}
|
||||
if case .undo = action {
|
||||
let _ = component.context.engine.contacts.addContactInteractively(peerId: peer.id, firstName: user.firstName ?? "", lastName: user.lastName ?? "", phoneNumber: user.phone ?? "", addToPrivacyExceptions: false).start()
|
||||
let _ = component.context.engine.contacts.addContactInteractively(peerId: peer.id, firstName: user.firstName ?? "", lastName: user.lastName ?? "", phoneNumber: user.phone ?? "", addToPrivacyExceptions: false).startStandalone()
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -3382,7 +3383,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}, action: { [weak self] _, f in
|
||||
f(.default)
|
||||
|
||||
let _ = component.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: true).start()
|
||||
let _ = component.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: true).startStandalone()
|
||||
|
||||
guard let self else {
|
||||
return
|
||||
@ -3412,7 +3413,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
return false
|
||||
}
|
||||
if case .undo = action {
|
||||
let _ = component.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: false).start()
|
||||
let _ = component.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: false).startStandalone()
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -4295,7 +4296,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
|
||||
if self.displayLikeReactions {
|
||||
if component.slice.item.storyItem.myReaction == updateReaction.reaction {
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id, reaction: nil).start()
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id, reaction: nil).startStandalone()
|
||||
self.displayLikeReactions = false
|
||||
self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut)))
|
||||
} else {
|
||||
@ -4306,12 +4307,12 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut)))
|
||||
|
||||
self.waitingForReactionAnimateOutToLike = updateReaction.reaction
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id, reaction: updateReaction.reaction).start()
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id, reaction: updateReaction.reaction).startStandalone()
|
||||
}
|
||||
} else {
|
||||
let _ = (component.context.engine.stickers.availableReactions()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak reactionContextNode] availableReactions in
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self, weak reactionContextNode] availableReactions in
|
||||
guard let self, let component = self.component, let availableReactions else {
|
||||
return
|
||||
}
|
||||
@ -4401,7 +4402,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
let peer = component.slice.peer
|
||||
|
||||
let _ = (enqueueMessages(account: context.account, peerId: peer.id, messages: [message])
|
||||
|> deliverOnMainQueue).start(next: { [weak self] messageIds in
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] messageIds in
|
||||
if let animation, let self, let component = self.component {
|
||||
let controller = UndoOverlayController(
|
||||
presentationData: presentationData,
|
||||
@ -4771,7 +4772,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
closeFriends: component.closeFriends.get(),
|
||||
blockedPeersContext: component.blockedPeers
|
||||
)
|
||||
let _ = (stateContext.ready |> filter { $0 } |> take(1) |> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
let _ = (stateContext.ready |> filter { $0 } |> take(1) |> deliverOnMainQueue).startStandalone(next: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -4788,7 +4789,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
self.updateIsProgressPaused()
|
||||
return
|
||||
}
|
||||
let _ = component.context.engine.messages.editStoryPrivacy(id: component.slice.item.storyItem.id, privacy: privacy).start()
|
||||
let _ = component.context.engine.messages.editStoryPrivacy(id: component.slice.item.storyItem.id, privacy: privacy).startStandalone()
|
||||
|
||||
self.presentPrivacyTooltip(privacy: privacy)
|
||||
|
||||
@ -4852,7 +4853,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
initialPeerIds: Set(privacy.additionallyIncludePeers),
|
||||
blockedPeersContext: component.blockedPeers
|
||||
)
|
||||
let _ = (stateContext.ready |> filter { $0 } |> take(1) |> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
let _ = (stateContext.ready |> filter { $0 } |> take(1) |> deliverOnMainQueue).startStandalone(next: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -4865,10 +4866,10 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
return
|
||||
}
|
||||
if blockedPeers, let blockedPeers = self?.component?.blockedPeers {
|
||||
let _ = blockedPeers.updatePeerIds(result.additionallyIncludePeers).start()
|
||||
let _ = blockedPeers.updatePeerIds(result.additionallyIncludePeers).startStandalone()
|
||||
completion(privacy)
|
||||
} else if case .closeFriends = privacy.base {
|
||||
let _ = context.engine.privacy.updateCloseFriends(peerIds: result.additionallyIncludePeers).start()
|
||||
let _ = context.engine.privacy.updateCloseFriends(peerIds: result.additionallyIncludePeers).startStandalone()
|
||||
if let component = self?.component {
|
||||
component.closeFriends.set(.single(peers))
|
||||
}
|
||||
@ -5096,7 +5097,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
|
||||
if let imageData = compressImageToJPEG(image, quality: 0.7) {
|
||||
updateDisposable.set((context.engine.messages.editStory(peerId: peerId, id: id, media: .image(dimensions: dimensions, data: imageData, stickers: stickers), mediaAreas: mediaAreas, text: updatedText, entities: updatedEntities, privacy: nil)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] result in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -5146,7 +5147,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
|
||||
updateDisposable.set((context.engine.messages.editStory(peerId: peerId, id: id, media: .video(dimensions: dimensions, duration: duration, resource: resource, firstFrameFile: firstFrameFile, stickers: stickers), mediaAreas: mediaAreas, text: updatedText, entities: updatedEntities, privacy: nil)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] result in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -5170,7 +5171,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
} else if updatedText != nil {
|
||||
let _ = (context.engine.messages.editStory(peerId: peerId, id: id, media: nil, mediaAreas: nil, text: updatedText, entities: updatedEntities, privacy: nil)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] result in
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] result in
|
||||
switch result {
|
||||
case .completed:
|
||||
Queue.mainQueue().after(0.1) {
|
||||
@ -5414,7 +5415,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id, reaction: component.slice.item.storyItem.myReaction == nil ? .builtin("❤") : nil).start()
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id, reaction: component.slice.item.storyItem.myReaction == nil ? .builtin("❤") : nil).startStandalone()
|
||||
|
||||
if component.slice.item.storyItem.myReaction != nil {
|
||||
return
|
||||
@ -5701,7 +5702,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = component.context.engine.messages.updateStoriesArePinned(peerId: component.slice.peer.id, ids: [component.slice.item.storyItem.id: component.slice.item.storyItem], isPinned: !component.slice.item.storyItem.isPinned).start()
|
||||
let _ = component.context.engine.messages.updateStoriesArePinned(peerId: component.slice.peer.id, ids: [component.slice.item.storyItem.id: component.slice.item.storyItem], isPinned: !component.slice.item.storyItem.isPinned).startStandalone()
|
||||
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
|
||||
if component.slice.item.storyItem.isPinned {
|
||||
@ -5765,7 +5766,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
|
||||
let _ = (component.context.engine.messages.exportStoryLink(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] link in
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] link in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
@ -5852,7 +5853,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = component.context.engine.messages.updateStoriesArePinned(peerId: component.slice.peer.id, ids: [component.slice.item.storyItem.id: component.slice.item.storyItem], isPinned: !component.slice.item.storyItem.isPinned).start()
|
||||
let _ = component.context.engine.messages.updateStoriesArePinned(peerId: component.slice.peer.id, ids: [component.slice.item.storyItem.id: component.slice.item.storyItem], isPinned: !component.slice.item.storyItem.isPinned).startStandalone()
|
||||
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
|
||||
if component.slice.item.storyItem.isPinned {
|
||||
@ -5900,7 +5901,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
|
||||
let _ = (component.context.engine.messages.exportStoryLink(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] link in
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] link in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
@ -6053,7 +6054,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
return translationSettings
|
||||
}
|
||||
|
||||
let _ = combineLatest(
|
||||
let _ = (combineLatest(
|
||||
queue: Queue.mainQueue(),
|
||||
component.context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: component.slice.peer.id),
|
||||
@ -6063,7 +6064,8 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: component.context.account.peerId)
|
||||
),
|
||||
translationSettings
|
||||
).start(next: { [weak self] result, translationSettings in
|
||||
)
|
||||
|> take(1)).startStandalone(next: { [weak self] result, translationSettings in
|
||||
guard let self, let component = self.component, let controller = component.controller() else {
|
||||
return
|
||||
}
|
||||
@ -6091,7 +6093,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = component.context.engine.peers.togglePeerStoriesMuted(peerId: component.slice.peer.id).start()
|
||||
let _ = component.context.engine.peers.togglePeerStoriesMuted(peerId: component.slice.peer.id).startStandalone()
|
||||
|
||||
let iconColor = UIColor.white
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
|
||||
@ -6237,7 +6239,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
|
||||
let _ = (component.context.engine.messages.exportStoryLink(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] link in
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] link in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
@ -6302,7 +6304,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
guard let self, let component = self.component, let controller = component.controller(), let reason else {
|
||||
return
|
||||
}
|
||||
let _ = component.context.engine.peers.reportPeerStory(peerId: component.slice.peer.id, storyId: component.slice.item.storyItem.id, reason: reason, message: "").start()
|
||||
let _ = component.context.engine.peers.reportPeerStory(peerId: component.slice.peer.id, storyId: component.slice.item.storyItem.id, reason: reason, message: "").startStandalone()
|
||||
controller.present(
|
||||
UndoOverlayController(
|
||||
presentationData: presentationData,
|
||||
@ -6376,7 +6378,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
|
||||
let _ = (ApplicationSpecificNotice.displayStoryUnmuteTooltip(accountManager: component.context.sharedContext.accountManager)
|
||||
|> delay(0.3, queue: .mainQueue())
|
||||
|> deliverOnMainQueue).start(next: { [weak self] value in
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] value in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
@ -6390,7 +6392,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
)
|
||||
component.controller()?.present(tooltipScreen, in: .current)
|
||||
|
||||
let _ = ApplicationSpecificNotice.setDisplayStoryUnmuteTooltip(accountManager: component.context.sharedContext.accountManager).start()
|
||||
let _ = ApplicationSpecificNotice.setDisplayStoryUnmuteTooltip(accountManager: component.context.sharedContext.accountManager).startStandalone()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
let hasActiveAudioSession = Promise<Bool>(false)
|
||||
|
||||
private let sharedContextPromise = Promise<SharedApplicationContext>()
|
||||
private let watchCommunicationManagerPromise = Promise<WatchCommunicationManager?>()
|
||||
//private let watchCommunicationManagerPromise = Promise<WatchCommunicationManager?>()
|
||||
|
||||
private var accountManager: AccountManager<TelegramAccountManagerTypes>?
|
||||
private var accountManagerState: AccountManagerState?
|
||||
@ -973,7 +973,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
let watchTasks = self.context.get()
|
||||
/*let watchTasks = self.context.get()
|
||||
|> mapToSignal { context -> Signal<AccountRecordId?, NoError> in
|
||||
if let context = context, let watchManager = context.context.watchManager {
|
||||
let accountId = context.context.account.id
|
||||
@ -992,7 +992,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
let wakeupManager = SharedWakeupManager(beginBackgroundTask: { name, expiration in
|
||||
let id = application.beginBackgroundTask(withName: name, expirationHandler: expiration)
|
||||
Logger.shared.log("App \(self.episodeId)", "Begin background task \(name): \(id)")
|
||||
@ -1004,7 +1004,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
application.endBackgroundTask(id)
|
||||
}, backgroundTimeRemaining: { application.backgroundTimeRemaining }, acquireIdleExtension: {
|
||||
return applicationBindings.pushIdleTimerExtension()
|
||||
}, activeAccounts: sharedContext.activeAccountContexts |> map { ($0.0?.account, $0.1.map { ($0.0, $0.1.account) }) }, liveLocationPolling: liveLocationPolling, watchTasks: watchTasks, inForeground: applicationBindings.applicationInForeground, hasActiveAudioSession: self.hasActiveAudioSession.get(), notificationManager: notificationManager, mediaManager: sharedContext.mediaManager, callManager: sharedContext.callManager, accountUserInterfaceInUse: { id in
|
||||
}, activeAccounts: sharedContext.activeAccountContexts |> map { ($0.0?.account, $0.1.map { ($0.0, $0.1.account) }) }, liveLocationPolling: liveLocationPolling, watchTasks: .single(nil), inForeground: applicationBindings.applicationInForeground, hasActiveAudioSession: self.hasActiveAudioSession.get(), notificationManager: notificationManager, mediaManager: sharedContext.mediaManager, callManager: sharedContext.callManager, accountUserInterfaceInUse: { id in
|
||||
return sharedContext.accountUserInterfaceInUse(id)
|
||||
})
|
||||
let sharedApplicationContext = SharedApplicationContext(sharedContext: sharedContext, notificationManager: notificationManager, wakeupManager: wakeupManager)
|
||||
@ -1023,7 +1023,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
return .single(sharedApplicationContext)
|
||||
})
|
||||
|
||||
let watchManagerArgumentsPromise = Promise<WatchManagerArguments?>()
|
||||
//let watchManagerArgumentsPromise = Promise<WatchManagerArguments?>()
|
||||
|
||||
self.context.set(self.sharedContextPromise.get()
|
||||
|> deliverOnMainQueue
|
||||
@ -1062,7 +1062,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
|> deliverOnMainQueue
|
||||
|> map { accountAndSettings -> AuthorizedApplicationContext? in
|
||||
return accountAndSettings.flatMap { context, callListSettings in
|
||||
return AuthorizedApplicationContext(sharedApplicationContext: sharedApplicationContext, mainWindow: self.mainWindow, watchManagerArguments: watchManagerArgumentsPromise.get(), context: context as! AccountContextImpl, accountManager: sharedApplicationContext.sharedContext.accountManager, showCallsTab: callListSettings.showTab, reinitializedNotificationSettings: {
|
||||
return AuthorizedApplicationContext(sharedApplicationContext: sharedApplicationContext, mainWindow: self.mainWindow, watchManagerArguments: .single(nil), context: context as! AccountContextImpl, accountManager: sharedApplicationContext.sharedContext.accountManager, showCallsTab: callListSettings.showTab, reinitializedNotificationSettings: {
|
||||
let _ = (self.context.get()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { context in
|
||||
@ -1305,7 +1305,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
}).start()
|
||||
}))
|
||||
|
||||
self.watchCommunicationManagerPromise.set(watchCommunicationManager(context: self.context.get() |> flatMap { WatchCommunicationManagerContext(context: $0.context) }, allowBackgroundTimeExtension: { timeout in
|
||||
/*self.watchCommunicationManagerPromise.set(watchCommunicationManager(context: self.context.get() |> flatMap { WatchCommunicationManagerContext(context: $0.context) }, allowBackgroundTimeExtension: { timeout in
|
||||
let _ = (self.sharedContextPromise.get()
|
||||
|> take(1)).start(next: { sharedContext in
|
||||
sharedContext.wakeupManager.allowBackgroundTimeExtension(timeout: timeout)
|
||||
@ -1317,7 +1317,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
} else {
|
||||
watchManagerArgumentsPromise.set(.single(nil))
|
||||
}
|
||||
})
|
||||
})*/
|
||||
|
||||
self.resetBadge()
|
||||
|
||||
|
@ -316,7 +316,7 @@
|
||||
{
|
||||
[_signalManager startSignalForKey:[NSString stringWithFormat:@"%lld", subscription.identifier] producer:^SSignal *
|
||||
{
|
||||
STimer *timer = [[STimer alloc] initWithTimeout:2.0 repeat:false completion:^
|
||||
STimer *timer = [[STimer alloc] initWithTimeout:2.0 repeat:false completion:^(__unused STimer *timer)
|
||||
{
|
||||
os_unfair_lock_lock(&_replyHandlerMapLock);
|
||||
void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)];
|
||||
|
Loading…
x
Reference in New Issue
Block a user