More memory leak fixes

This commit is contained in:
Ali 2023-09-22 18:09:36 +04:00
parent 040e8b2da0
commit 403dd188a4
53 changed files with 444 additions and 881 deletions

View File

@ -1189,8 +1189,7 @@ ActionStage *ActionStageInstance()
{ {
TGLegacyLog(@"Will cancel request to \"%@\" in %f s", path, cancelTimeout); TGLegacyLog(@"Will cancel request to \"%@\" in %f s", path, cancelTimeout);
NSDictionary *cancelDict = [NSDictionary dictionaryWithObjectsAndKeys:path, @"path", [NSNumber numberWithInt:0], @"type", nil]; 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]; [self performCancelRequest:cancelDict];
} nativeQueue:[ActionStageInstance() globalStageDispatchQueue]]; } nativeQueue:[ActionStageInstance() globalStageDispatchQueue]];

View File

@ -96,7 +96,7 @@
[self setChecked:[self.selectionContext isItemSelected:(id<TGMediaSelectableItem>)asset] animated:false]; [self setChecked:[self.selectionContext isItemSelected:(id<TGMediaSelectableItem>)asset] animated:false];
__weak TGAttachmentAssetCell *weakSelf = self; __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; __strong TGAttachmentAssetCell *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -104,7 +104,7 @@
if (next.sender != strongSelf->_checkButton) if (next.sender != strongSelf->_checkButton)
[strongSelf setChecked:next.selected animated:next.animated]; [strongSelf setChecked:next.selected animated:next.animated];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
if (_asset == nil) if (_asset == nil)

View File

@ -174,7 +174,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
return [SSignal complete]; return [SSignal complete];
return [[strongSelf->_collectionView noOngoingTransitionSignal] then:[SSignal single:value]]; return [[strongSelf->_collectionView noOngoingTransitionSignal] then:[SSignal single:value]];
}] startWithNext:^(__unused TGMediaSelectionChange *change) }] startStrictWithNext:^(__unused TGMediaSelectionChange *change)
{ {
__strong TGAttachmentCarouselItemView *strongSelf = weakSelf; __strong TGAttachmentCarouselItemView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -190,7 +190,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
[strongSelf updateSendButtonsFromIndex:index]; [strongSelf updateSendButtonsFromIndex:index];
[strongSelf updateSelectionIndexes]; [strongSelf updateSelectionIndexes];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
if (allowEditing) if (allowEditing)
@ -198,7 +198,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
_editingContext = [[TGMediaEditingContext alloc] init]; _editingContext = [[TGMediaEditingContext alloc] init];
_itemsSizeChangedDisposable = [[SMetaDisposable 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; __strong TGAttachmentCarouselItemView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -217,7 +217,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
[strongSelf centerOnItemWithIndex:indexPath.row animated:false]; [strongSelf centerOnItemWithIndex:indexPath.row animated:false];
} }
} }
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
_smallLayout = [[UICollectionViewFlowLayout alloc] init]; _smallLayout = [[UICollectionViewFlowLayout alloc] init];
@ -430,7 +430,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
return [SSignal complete]; return [SSignal complete];
return [[strongSelf->_collectionView noOngoingTransitionSignal] then:[SSignal single:value]]; return [[strongSelf->_collectionView noOngoingTransitionSignal] then:[SSignal single:value]];
}] deliverOn:[SQueue mainQueue]] startWithNext:^(id next) }] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id next)
{ {
__strong TGAttachmentCarouselItemView *strongSelf = weakSelf; __strong TGAttachmentCarouselItemView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -456,7 +456,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
if (strongSelf->_galleryMixin != nil && strongSelf->_fetchResult != nil) if (strongSelf->_galleryMixin != nil && strongSelf->_fetchResult != nil)
[strongSelf->_galleryMixin updateWithFetchResult:strongSelf->_fetchResult]; [strongSelf->_galleryMixin updateWithFetchResult:strongSelf->_fetchResult];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (SSignal *)_signalForItem:(TGMediaAsset *)asset - (SSignal *)_signalForItem:(TGMediaAsset *)asset

View File

@ -64,7 +64,7 @@ NSString *const TGAttachmentVideoCellIdentifier = @"AttachmentVideoCell";
SSignal *adjustmentsSignal = [self.editingContext adjustmentsSignalForItem:self.asset]; SSignal *adjustmentsSignal = [self.editingContext adjustmentsSignalForItem:self.asset];
__weak TGAttachmentVideoCell *weakSelf = self; __weak TGAttachmentVideoCell *weakSelf = self;
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startWithNext:^(TGVideoEditAdjustments *next) [_adjustmentsDisposable setDisposable:[adjustmentsSignal startStrictWithNext:^(TGVideoEditAdjustments *next)
{ {
__strong TGAttachmentVideoCell *strongSelf = weakSelf; __strong TGAttachmentVideoCell *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -74,7 +74,7 @@ NSString *const TGAttachmentVideoCellIdentifier = @"AttachmentVideoCell";
[strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation]; [strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation];
else else
[strongSelf _layoutImageWithoutAdjustments]; [strongSelf _layoutImageWithoutAdjustments];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (void)_transformLayoutForOrientation:(UIImageOrientation)orientation originalSize:(CGSize *)inOriginalSize cropRect:(CGRect *)inCropRect - (void)_transformLayoutForOrientation:(UIImageOrientation)orientation originalSize:(CGSize *)inOriginalSize cropRect:(CGRect *)inCropRect

View File

@ -304,7 +304,7 @@ NSString *TGImageViewOptionSynchronous = @"TGImageViewOptionSynchronous";
int version = _version; int version = _version;
__weak TGImageView *weakSelf = self; __weak TGImageView *weakSelf = self;
[_disposable setDisposable:[signal startWithNext:^(id next) [_disposable setDisposable:[signal startStrictWithNext:^(id next)
{ {
bool synchronous = [NSThread isMainThread]; bool synchronous = [NSThread isMainThread];
TGDispatchOnMainThread(^ TGDispatchOnMainThread(^
@ -323,7 +323,7 @@ NSString *TGImageViewOptionSynchronous = @"TGImageViewOptionSynchronous";
TGLegacyLog(@"TGImageView signal error: %@", error); TGLegacyLog(@"TGImageView signal error: %@", error);
} completed:^ } completed:^
{ {
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
@end @end

View File

@ -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)]; [subscriber putNext:@(exportSession.progress)];
} queue:[SQueue concurrentDefaultQueue]]; } queue:[SQueue concurrentDefaultQueue]];
[progressTimer start]; [progressTimer start];

View File

@ -491,7 +491,7 @@
}; };
_selectionChangedDisposable = [[SMetaDisposable alloc] init]; _selectionChangedDisposable = [[SMetaDisposable alloc] init];
[_selectionChangedDisposable setDisposable:[[_selectionContext selectionChangedSignal] startWithNext:^(__unused id next) [_selectionChangedDisposable setDisposable:[[_selectionContext selectionChangedSignal] startStrictWithNext:^(__unused id next)
{ {
__strong TGMediaAssetsController *strongSelf = weakSelf; __strong TGMediaAssetsController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -540,7 +540,7 @@
} }
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, text); UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, text);
}]]; } file:__FILE_NAME__ line:__LINE__]];
if (intent == TGMediaAssetsControllerSendMediaIntent || intent == TGMediaAssetsControllerSetProfilePhotoIntent || intent == TGMediaAssetsControllerSetSignupProfilePhotoIntent || intent == TGMediaAssetsControllerPassportIntent || intent == TGMediaAssetsControllerPassportMultipleIntent) if (intent == TGMediaAssetsControllerSendMediaIntent || intent == TGMediaAssetsControllerSetProfilePhotoIntent || intent == TGMediaAssetsControllerSetSignupProfilePhotoIntent || intent == TGMediaAssetsControllerPassportIntent || intent == TGMediaAssetsControllerPassportMultipleIntent)
_editingContext = [[TGMediaEditingContext alloc] init]; _editingContext = [[TGMediaEditingContext alloc] init];
@ -550,28 +550,28 @@
if (allowGrouping) if (allowGrouping)
{ {
_groupingChangedDisposable = [[SMetaDisposable alloc] init]; _groupingChangedDisposable = [[SMetaDisposable alloc] init];
[_groupingChangedDisposable setDisposable:[_selectionContext.groupingChangedSignal startWithNext:^(NSNumber *next) [_groupingChangedDisposable setDisposable:[_selectionContext.groupingChangedSignal startStrictWithNext:^(NSNumber *next)
{ {
__strong TGMediaAssetsController *strongSelf = weakSelf; __strong TGMediaAssetsController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
return; return;
[strongSelf->_toolbarView setCenterButtonSelected:next.boolValue]; [strongSelf->_toolbarView setCenterButtonSelected:next.boolValue];
}]]; } file:__FILE_NAME__ line:__LINE__]];
if (_editingContext != nil) if (_editingContext != nil)
{ {
_timersChangedDisposable = [[SMetaDisposable alloc] init]; _timersChangedDisposable = [[SMetaDisposable alloc] init];
[_timersChangedDisposable setDisposable:[_editingContext.timersUpdatedSignal startWithNext:^(__unused NSNumber *next) [_timersChangedDisposable setDisposable:[_editingContext.timersUpdatedSignal startStrictWithNext:^(__unused NSNumber *next)
{ {
updateGroupingButtonVisibility(); updateGroupingButtonVisibility();
}]]; } file:__FILE_NAME__ line:__LINE__]];
_adjustmentsChangedDisposable = [[SMetaDisposable alloc] init]; _adjustmentsChangedDisposable = [[SMetaDisposable alloc] init];
[_adjustmentsChangedDisposable setDisposable:[_editingContext.adjustmentsUpdatedSignal startWithNext:^(__unused NSNumber *next) [_adjustmentsChangedDisposable setDisposable:[_editingContext.adjustmentsUpdatedSignal startStrictWithNext:^(__unused NSNumber *next)
{ {
updateGroupingButtonVisibility(); updateGroupingButtonVisibility();
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
} }
} }
@ -1873,11 +1873,11 @@
_tooltipDismissDisposable = [[SMetaDisposable alloc] init]; _tooltipDismissDisposable = [[SMetaDisposable alloc] init];
__weak TGTooltipContainerView *weakContainerView = _groupingTooltipContainerView; __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; __strong TGTooltipContainerView *strongContainerView = weakContainerView;
if (strongContainerView != nil) if (strongContainerView != nil)
[strongContainerView hideTooltip]; [strongContainerView hideTooltip];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (BOOL)prefersStatusBarHidden - (BOOL)prefersStatusBarHidden

View File

@ -134,12 +134,12 @@
return [strongSelf _itemAtIndexPath:indexPath]; return [strongSelf _itemAtIndexPath:indexPath];
}; };
_selectionChangedDisposable = [[self.selectionContext selectionChangedSignal] startWithNext:^(id next) _selectionChangedDisposable = [[self.selectionContext selectionChangedSignal] startStrictWithNext:^(id next)
{ {
__strong TGMediaAssetsPickerController *strongSelf = weakSelf; __strong TGMediaAssetsPickerController *strongSelf = weakSelf;
if (strongSelf != nil) if (strongSelf != nil)
return [strongSelf updateSelectionIndexes]; return [strongSelf updateSelectionIndexes];
}]; } file:__FILE_NAME__ line:__LINE__];
} }
- (void)updateSelectionIndexes - (void)updateSelectionIndexes
@ -194,7 +194,7 @@
[strongSelf setTitle:assetGroup.title]; [strongSelf setTitle:assetGroup.title];
} }
return [strongSelf->_assetsLibrary assetsOfAssetGroup:assetGroup reversed:reversed]; return [strongSelf->_assetsLibrary assetsOfAssetGroup:assetGroup reversed:reversed];
}] deliverOn:[SQueue mainQueue]] startWithNext:^(id next) }] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id next)
{ {
__strong TGMediaAssetsPickerController *strongSelf = weakSelf; __strong TGMediaAssetsPickerController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -238,7 +238,7 @@
if (strongSelf->_galleryMixin != nil && strongSelf->_fetchResult != nil) if (strongSelf->_galleryMixin != nil && strongSelf->_fetchResult != nil)
[strongSelf->_galleryMixin updateWithFetchResult:strongSelf->_fetchResult]; [strongSelf->_galleryMixin updateWithFetchResult:strongSelf->_fetchResult];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (void)viewWillAppear:(BOOL)animated - (void)viewWillAppear:(BOOL)animated

View File

@ -112,7 +112,7 @@ NSString *const TGMediaAssetsVideoCellKind = @"TGMediaAssetsVideoCellKind";
SSignal *adjustmentsSignal = [self.editingContext adjustmentsSignalForItem:(id<TGMediaEditableItem>)self.item]; SSignal *adjustmentsSignal = [self.editingContext adjustmentsSignalForItem:(id<TGMediaEditableItem>)self.item];
__weak TGMediaAssetsVideoCell *weakSelf = self; __weak TGMediaAssetsVideoCell *weakSelf = self;
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startWithNext:^(TGVideoEditAdjustments *next) [_adjustmentsDisposable setDisposable:[adjustmentsSignal startStrictWithNext:^(TGVideoEditAdjustments *next)
{ {
__strong TGMediaAssetsVideoCell *strongSelf = weakSelf; __strong TGMediaAssetsVideoCell *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -122,7 +122,7 @@ NSString *const TGMediaAssetsVideoCellKind = @"TGMediaAssetsVideoCellKind";
[strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation]; [strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation];
else else
[strongSelf _layoutImageWithoutAdjustments]; [strongSelf _layoutImageWithoutAdjustments];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (void)_transformLayoutForOrientation:(UIImageOrientation)orientation originalSize:(CGSize *)inOriginalSize cropRect:(CGRect *)inCropRect - (void)_transformLayoutForOrientation:(UIImageOrientation)orientation originalSize:(CGSize *)inOriginalSize cropRect:(CGRect *)inCropRect

View File

@ -104,7 +104,7 @@
__weak TGMediaGroupsController *weakSelf = self; __weak TGMediaGroupsController *weakSelf = self;
_groupsDisposable = [[SMetaDisposable alloc] init]; _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; __strong TGMediaGroupsController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -131,7 +131,7 @@
if (![next containsObject:pickerController.assetGroup]) if (![next containsObject:pickerController.assetGroup])
[strongSelf.navigationController popToRootViewControllerAnimated:false]; [strongSelf.navigationController popToRootViewControllerAnimated:false];
} }
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (void)viewWillAppear:(BOOL)animated - (void)viewWillAppear:(BOOL)animated

View File

@ -80,7 +80,7 @@
__weak TGMediaPickerCell *weakSelf = self; __weak TGMediaPickerCell *weakSelf = self;
[self setChecked:[self.selectionContext isItemSelected:(id<TGMediaSelectableItem>)item] animated:false]; [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; __strong TGMediaPickerCell *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -88,7 +88,7 @@
if (next.sender != strongSelf->_checkButton) if (next.sender != strongSelf->_checkButton)
[strongSelf setChecked:next.selected animated:next.animated]; [strongSelf setChecked:next.selected animated:next.animated];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
if (_item == nil) if (_item == nil)

View File

@ -134,6 +134,12 @@
_actionHandle = [[ASHandle alloc] initWithDelegate:self releaseOnMainThread:true]; _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; _context = context;
_selectionContext = selectionContext; _selectionContext = selectionContext;
_editingContext = editingContext; _editingContext = editingContext;
@ -255,7 +261,7 @@
_photoCounterButton.userInteractionEnabled = false; _photoCounterButton.userInteractionEnabled = false;
[_wrapperView addSubview:_photoCounterButton]; [_wrapperView addSubview:_photoCounterButton];
_selectionChangedDisposable = [[_selectionContext selectionChangedSignal] startWithNext:^(id next) _selectionChangedDisposable = [[_selectionContext selectionChangedSignal] startStrictWithNext:^(id next)
{ {
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf; __strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -269,29 +275,29 @@
[strongSelf->_checkButton setNumber:[strongSelf->_selectionContext indexOfItem:selectableItem]]; [strongSelf->_checkButton setNumber:[strongSelf->_selectionContext indexOfItem:selectableItem]];
[strongSelf updateGroupingButtonVisibility]; [strongSelf updateGroupingButtonVisibility];
}]; } file:__FILE_NAME__ line:__LINE__];
if (_selectionContext.allowGrouping) if (_selectionContext.allowGrouping)
{ {
if (_editingContext != nil) if (_editingContext != nil)
{ {
_timersChangedDisposable = [_editingContext.timersUpdatedSignal startWithNext:^(__unused NSNumber *next) _timersChangedDisposable = [_editingContext.timersUpdatedSignal startStrictWithNext:^(__unused NSNumber *next)
{ {
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf; __strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
return; return;
[strongSelf updateGroupingButtonVisibility]; [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; __strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
return; return;
[strongSelf updateGroupingButtonVisibility]; [strongSelf updateGroupingButtonVisibility];
}]; } file:__FILE_NAME__ line:__LINE__];
} }
[self updateGroupingButtonVisibility]; [self updateGroupingButtonVisibility];
@ -300,11 +306,6 @@
[self updateEditorButtonsForItem:focusItem animated:false]; [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 = [[TGPhotoCaptionInputMixin alloc] init];
_captionMixin.panelParentView = ^UIView * _captionMixin.panelParentView = ^UIView *
{ {
@ -418,6 +419,7 @@
[_itemAvailabilityDisposable dispose]; [_itemAvailabilityDisposable dispose];
[_selectionChangedDisposable dispose]; [_selectionChangedDisposable dispose];
[_timersChangedDisposable dispose]; [_timersChangedDisposable dispose];
[_adjustmentsChangedDisposable dispose];
} }
- (bool)updateGroupingButtonVisibility - (bool)updateGroupingButtonVisibility
@ -566,7 +568,7 @@
} }
[_checkButton setNumber:[_selectionContext indexOfItem:selectableItem]]; [_checkButton setNumber:[_selectionContext indexOfItem:selectableItem]];
signal = [_selectionContext itemInformativeSelectedSignal:selectableItem]; signal = [_selectionContext itemInformativeSelectedSignal:selectableItem];
[_itemSelectedDisposable setDisposable:[signal startWithNext:^(TGMediaSelectionChange *next) [_itemSelectedDisposable setDisposable:[signal startStrictWithNext:^(TGMediaSelectionChange *next)
{ {
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf; __strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -574,13 +576,13 @@
if (next.sender != strongSelf->_checkButton) if (next.sender != strongSelf->_checkButton)
[strongSelf->_checkButton setSelected:next.selected animated:next.animated]; [strongSelf->_checkButton setSelected:next.selected animated:next.animated];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
[self updateEditorButtonsForItem:item animated:true]; [self updateEditorButtonsForItem:item animated:true];
__weak TGModernGalleryItemView *weakItemView = itemView; __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 TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
__strong TGModernGalleryItemView *strongItemView = weakItemView; __strong TGModernGalleryItemView *strongItemView = weakItemView;
@ -611,7 +613,7 @@
} }
strongSelf->_muteButton.hidden = !sendableAsGif; strongSelf->_muteButton.hidden = !sendableAsGif;
} }
}]]; } file:__FILE_NAME__ line:__LINE__]];
UIImage *muteIcon = [TGPhotoEditorInterfaceAssets muteIcon]; UIImage *muteIcon = [TGPhotoEditorInterfaceAssets muteIcon];
UIImage *muteActiveIcon = [TGPhotoEditorInterfaceAssets muteActiveIcon]; UIImage *muteActiveIcon = [TGPhotoEditorInterfaceAssets muteActiveIcon];
@ -764,13 +766,13 @@
if ([item conformsToProtocol:@protocol(TGModernGalleryEditableItem)]) if ([item conformsToProtocol:@protocol(TGModernGalleryEditableItem)])
{ {
id<TGMediaEditableItem> editableMediaItem = [galleryEditableItem editableMediaItem]; 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; __strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
return; return;
[strongSelf->_captionMixin setCaption:caption animated:animated]; [strongSelf->_captionMixin setCaption:caption animated:animated];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
if (_editingContext == nil || _editingContext.inhibitEditing) if (_editingContext == nil || _editingContext.inhibitEditing)
@ -829,7 +831,7 @@
} else { } else {
return [SSignal never]; return [SSignal never];
} }
}] deliverOn:[SQueue mainQueue]] startWithNext:^(NSDictionary *dict) }] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSDictionary *dict)
{ {
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf; __strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -855,7 +857,7 @@
originalSize = editableMediaItem.originalSize; originalSize = editableMediaItem.originalSize;
[strongSelf updateEditorButtonsForAdjustments:adjustments dimensions:originalSize timer:timer]; [strongSelf updateEditorButtonsForAdjustments:adjustments dimensions:originalSize timer:timer];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
else else
{ {

View File

@ -215,7 +215,7 @@
}]; }];
SSignal *adjustmentsSignal = [item.editingContext adjustmentsSignalForItem:item.editableMediaItem]; 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; __strong TGMediaPickerGalleryPhotoItemView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -223,7 +223,7 @@
[strongSelf layoutEntities]; [strongSelf layoutEntities];
[strongSelf->_entitiesView setupWithEntitiesData:next.paintingData.entitiesData]; [strongSelf->_entitiesView setupWithEntitiesData:next.paintingData.entitiesData];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
if (item.immediateThumbnailImage != nil) if (item.immediateThumbnailImage != nil)
@ -249,7 +249,7 @@
}]]; }]];
if (!item.asFile) { 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; return;
} }
@ -261,7 +261,7 @@
if ([item.asset isKindOfClass:[TGMediaAsset class]]) 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; __strong TGMediaPickerGalleryPhotoItemView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -276,7 +276,7 @@
} else { } else {
strongSelf->_fileInfoLabel.text = dimensions; strongSelf->_fileInfoLabel.text = dimensions;
} }
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
} }
} }

View File

@ -37,7 +37,7 @@
{ {
__weak TGMediaPickerGallerySelectedItemsModel *weakSelf = self; __weak TGMediaPickerGallerySelectedItemsModel *weakSelf = self;
_selectionChangedDisposable = [[SMetaDisposable alloc] init]; _selectionChangedDisposable = [[SMetaDisposable alloc] init];
[_selectionChangedDisposable setDisposable:[[selectionContext selectionChangedSignal] startWithNext:^(TGMediaSelectionChange *next) [_selectionChangedDisposable setDisposable:[[selectionContext selectionChangedSignal] startStrictWithNext:^(TGMediaSelectionChange *next)
{ {
__strong TGMediaPickerGallerySelectedItemsModel *strongSelf = weakSelf; __strong TGMediaPickerGallerySelectedItemsModel *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -53,7 +53,7 @@
[strongSelf addSelectedItem:next.item]; [strongSelf addSelectedItem:next.item];
else if (!strongSelf->_keepItems) else if (!strongSelf->_keepItems)
[strongSelf removeSelectedItem:next.item]; [strongSelf removeSelectedItem:next.item];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
} }
return self; return self;

View File

@ -354,7 +354,7 @@
[self setProgressVisible:true value:0.027 animated:true]; [self setProgressVisible:true value:0.027 animated:true];
__weak TGMediaPickerGalleryVideoItemView *weakSelf = self; __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; __strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -379,7 +379,7 @@
strongSelf->_downloaded = true; strongSelf->_downloaded = true;
if (strongSelf->_currentAvailabilityObserver != nil) if (strongSelf->_currentAvailabilityObserver != nil)
strongSelf->_currentAvailabilityObserver(true); strongSelf->_currentAvailabilityObserver(true);
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (id<TGModernGalleryItem>)item { - (id<TGModernGalleryItem>)item {
@ -413,7 +413,7 @@
[self _playerCleanup]; [self _playerCleanup];
if (!item.asFile) { 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) { SSignal *adjustmentsSignal = [[self editableItemSignal] mapToSignal:^SSignal *(id<TGMediaEditableItem> editableItem) {
return [item.editingContext adjustmentsSignalForItem: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; __strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -512,7 +512,7 @@
if (!strongSelf.isPlaying) { if (!strongSelf.isPlaying) {
[strongSelf->_photoEditor reprocess]; [strongSelf->_photoEditor reprocess];
} }
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
else else
{ {
@ -532,7 +532,7 @@
} }
_fileInfoLabel.text = nil; _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; __strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -546,7 +546,7 @@
[components addObject:[TGMediaPickerGalleryVideoItemView _stringForDimensions:next.dimensions]]; [components addObject:[TGMediaPickerGalleryVideoItemView _stringForDimensions:next.dimensions]];
strongSelf->_fileInfoLabel.text = [components componentsJoinedByString:@" • "]; strongSelf->_fileInfoLabel.text = [components componentsJoinedByString:@" • "];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (void)setIsCurrent:(bool)isCurrent - (void)setIsCurrent:(bool)isCurrent
@ -576,7 +576,7 @@
__weak TGMediaPickerGalleryVideoItemView *weakSelf = self; __weak TGMediaPickerGalleryVideoItemView *weakSelf = self;
void (^block)(void) = ^ 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; __strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil || next == nil) if (strongSelf == nil || next == nil)
@ -611,7 +611,7 @@
[strongSelf->_scrubberView resetToStart]; [strongSelf->_scrubberView resetToStart];
strongSelf->_appeared = true; strongSelf->_appeared = true;
} }
}]]; } file:__FILE_NAME__ line:__LINE__]];
}; };
if (_scrubberView.frame.size.width < FLT_EPSILON) 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; __strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil || ![playerItem isKindOfClass:[AVPlayerItem class]]) if (strongSelf == nil || ![playerItem isKindOfClass:[AVPlayerItem class]])
@ -1206,7 +1206,7 @@
[strongSelf positionTimerEvent]; [strongSelf positionTimerEvent];
[strongSelf _mutePlayer:strongSelf->_sendAsGif]; [strongSelf _mutePlayer:strongSelf->_sendAsGif];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)__unused change context:(void *)__unused context - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)__unused change context:(void *)__unused context
@ -1682,7 +1682,7 @@
} else { } else {
return images; return images;
} }
}] deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *images) }] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSArray *images)
{ {
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf; __strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -1698,7 +1698,7 @@
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf; __strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf != nil) if (strongSelf != nil)
strongSelf->_requestingThumbnails = false; strongSelf->_requestingThumbnails = false;
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (void)videoScrubberDidFinishRequestingThumbnails:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber - (void)videoScrubberDidFinishRequestingThumbnails:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber

View File

@ -149,7 +149,7 @@ NSString *const TGMediaPickerPhotoStripCellKind = @"PhotoStripCell";
[self setChecked:[self.selectionContext isItemSelected:(id<TGMediaSelectableItem>)item] animated:false]; [self setChecked:[self.selectionContext isItemSelected:(id<TGMediaSelectableItem>)item] animated:false];
__weak TGMediaPickerPhotoStripCell *weakSelf = self; __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; __strong TGMediaPickerPhotoStripCell *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -157,7 +157,7 @@ NSString *const TGMediaPickerPhotoStripCellKind = @"PhotoStripCell";
if (![next.sender isKindOfClass:[TGMediaPickerGallerySelectedItemsModel class]]) if (![next.sender isKindOfClass:[TGMediaPickerGallerySelectedItemsModel class]])
[strongSelf setChecked:next.selected animated:next.animated]; [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]; SSignal *adjustmentsSignal = [self.editingContext adjustmentsSignalForItem:video];
__weak TGMediaPickerPhotoStripCell *weakSelf = self; __weak TGMediaPickerPhotoStripCell *weakSelf = self;
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startWithNext:^(TGVideoEditAdjustments *next) [_adjustmentsDisposable setDisposable:[adjustmentsSignal startStrictWithNext:^(TGVideoEditAdjustments *next)
{ {
__strong TGMediaPickerPhotoStripCell *strongSelf = weakSelf; __strong TGMediaPickerPhotoStripCell *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -191,7 +191,7 @@ NSString *const TGMediaPickerPhotoStripCellKind = @"PhotoStripCell";
[strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation]; [strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation];
else else
[strongSelf _layoutImageWithoutAdjustments]; [strongSelf _layoutImageWithoutAdjustments];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
return; return;
} }
@ -221,7 +221,7 @@ NSString *const TGMediaPickerPhotoStripCellKind = @"PhotoStripCell";
SSignal *adjustmentsSignal = [self.editingContext adjustmentsSignalForItem:asset]; SSignal *adjustmentsSignal = [self.editingContext adjustmentsSignalForItem:asset];
__weak TGMediaPickerPhotoStripCell *weakSelf = self; __weak TGMediaPickerPhotoStripCell *weakSelf = self;
[_adjustmentsDisposable setDisposable:[adjustmentsSignal startWithNext:^(TGVideoEditAdjustments *next) [_adjustmentsDisposable setDisposable:[adjustmentsSignal startStrictWithNext:^(TGVideoEditAdjustments *next)
{ {
__strong TGMediaPickerPhotoStripCell *strongSelf = weakSelf; __strong TGMediaPickerPhotoStripCell *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -231,7 +231,7 @@ NSString *const TGMediaPickerPhotoStripCellKind = @"PhotoStripCell";
[strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation]; [strongSelf _layoutImageForOriginalSize:next.originalSize cropRect:next.cropRect cropOrientation:next.cropOrientation];
else else
[strongSelf _layoutImageWithoutAdjustments]; [strongSelf _layoutImageWithoutAdjustments];
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
} }
break; break;

View File

@ -282,7 +282,7 @@
return strongSelf.updatedItemsSignal(selectedItems); return strongSelf.updatedItemsSignal(selectedItems);
return [SSignal fail:nil]; return [SSignal fail:nil];
}] deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *next) }] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSArray *next)
{ {
__strong TGMediaSelectionContext *strongSelf = weakSelf; __strong TGMediaSelectionContext *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -304,7 +304,7 @@
for (NSString *identifier in deletedItemsIdentifiers) for (NSString *identifier in deletedItemsIdentifiers)
strongSelf->_pipe.sink([TGMediaSelectionChange changeWithItem:previousItemsMap[identifier] selected:false animated:false sender:nil]); strongSelf->_pipe.sink([TGMediaSelectionChange changeWithItem:previousItemsMap[identifier] selected:false animated:false sender:nil]);
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
#pragma mark - #pragma mark -

View File

@ -140,7 +140,7 @@ typedef enum
__weak TGMenuSheetController *weakSelf = self; __weak TGMenuSheetController *weakSelf = self;
_sizeClassDisposable = [[SMetaDisposable alloc] init]; _sizeClassDisposable = [[SMetaDisposable alloc] init];
[_sizeClassDisposable setDisposable:[[_context sizeClassSignal] startWithNext:^(NSNumber *next) [_sizeClassDisposable setDisposable:[[_context sizeClassSignal] startStrictWithNext:^(NSNumber *next)
{ {
__strong TGMenuSheetController *strongSelf = weakSelf; __strong TGMenuSheetController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -148,7 +148,7 @@ typedef enum
UIUserInterfaceSizeClass sizeClass = next.integerValue; UIUserInterfaceSizeClass sizeClass = next.integerValue;
[strongSelf updateTraitsWithSizeClass:sizeClass]; [strongSelf updateTraitsWithSizeClass:sizeClass];
}]]; } file:__FILE_NAME__ line:__LINE__]];
_containerView = [[TGMenuSheetContainerView alloc] initWithFrame:CGRectZero]; _containerView = [[TGMenuSheetContainerView alloc] initWithFrame:CGRectZero];
[self.view addSubview:_containerView]; [self.view addSubview:_containerView];

View File

@ -661,7 +661,7 @@ static void adjustFrameRate(CAAnimation *animation) {
if (_asyncTransitionIn) { if (_asyncTransitionIn) {
__weak TGModernGalleryController *weakSelf = self; __weak TGModernGalleryController *weakSelf = self;
self.view.hidden = true; 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; __strong TGModernGalleryController *strongSelf = weakSelf;
if (strongSelf != nil) { if (strongSelf != nil) {
[strongSelf animateTransitionInFromView:transitionInFromView toView:transitionInToView toViewContentRect:transitionInToViewContentRect]; [strongSelf animateTransitionInFromView:transitionInFromView toView:transitionInToView toViewContentRect:transitionInToViewContentRect];
@ -674,7 +674,7 @@ static void adjustFrameRate(CAAnimation *animation) {
strongSelf->_startedTransitionIn(); strongSelf->_startedTransitionIn();
} }
} }
}]; } file:__FILE_NAME__ line:__LINE__];
} else { } else {
if (_startedTransitionIn) { if (_startedTransitionIn) {
_startedTransitionIn(); _startedTransitionIn();

View File

@ -304,7 +304,7 @@
{ {
__weak TGNavigationController *weakSelf = self; __weak TGNavigationController *weakSelf = self;
[_playerStatusDisposable dispose]; [_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; __strong TGNavigationController *strongSelf = weakSelf;
if (strongSelf != nil) if (strongSelf != nil)
@ -327,7 +327,7 @@
}]; }];
} }
} }
}]; } file:__FILE_NAME__ line:__LINE__];
} }
else else
{ {

View File

@ -68,7 +68,7 @@
__weak TGPassportScanView *weakSelf = self; __weak TGPassportScanView *weakSelf = self;
[_camera captureNextFrameCompletion:^(UIImage *image) [_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; __strong TGPassportScanView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -85,7 +85,7 @@
{ {
strongSelf->_timer = [TGTimerTarget scheduledMainThreadTimerWithTarget:self action:@selector(handleNextFrame) interval:0.45 repeat:false]; strongSelf->_timer = [TGTimerTarget scheduledMainThreadTimerWithTarget:self action:@selector(handleNextFrame) interval:0.45 repeat:false];
} }
}]]; } file:__FILE_NAME__ line:__LINE__]];
}]; }];
} }

View File

@ -539,8 +539,7 @@ const CGFloat TGPhotoCropViewOverscreenSize = 1000;
__weak TGPhotoCropView *weakSelf = self; __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; __strong TGPhotoCropView *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
return; return;

View File

@ -2618,7 +2618,7 @@
[_faceDetectorDisposable setDisposable:[[[cachedSignal catch:^SSignal *(__unused id error) [_faceDetectorDisposable setDisposable:[[[cachedSignal catch:^SSignal *(__unused id error)
{ {
return detectSignal; return detectSignal;
}] deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *next) }] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSArray *next)
{ {
__strong TGPhotoEditorController *strongSelf = weakSelf; __strong TGPhotoEditorController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -2630,7 +2630,7 @@
return; return;
strongSelf->_faces = next; strongSelf->_faces = next;
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
+ (TGPhotoEditorTab)defaultTabsForAvatarIntent:(bool)hasStickers + (TGPhotoEditorTab)defaultTabsForAvatarIntent:(bool)hasStickers
@ -3014,7 +3014,7 @@
} else { } else {
return images; return images;
} }
}] deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *images) }] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSArray *images)
{ {
__strong TGPhotoEditorController *strongSelf = weakSelf; __strong TGPhotoEditorController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -3039,7 +3039,7 @@
__strong TGPhotoEditorController *strongSelf = weakSelf; __strong TGPhotoEditorController *strongSelf = weakSelf;
if (strongSelf != nil) if (strongSelf != nil)
strongSelf->_requestingThumbnails = false; strongSelf->_requestingThumbnails = false;
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (void)videoScrubberDidFinishRequestingThumbnails:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber - (void)videoScrubberDidFinishRequestingThumbnails:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber

View File

@ -217,7 +217,7 @@
- (void)setHistogramSignal:(SSignal *)signal - (void)setHistogramSignal:(SSignal *)signal
{ {
__weak TGPhotoEditorCurvesHistogramView *weakSelf = self; __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; __strong TGPhotoEditorCurvesHistogramView *strongSelf = weakSelf;
if (strongSelf != nil) if (strongSelf != nil)
@ -225,7 +225,7 @@
strongSelf->_histogram = next; strongSelf->_histogram = next;
[strongSelf updateHistogram]; [strongSelf updateHistogram];
} }
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
@synthesize interactionBegan; @synthesize interactionBegan;

View File

@ -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; __strong TGPhotoQualityController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -781,7 +781,7 @@ const NSTimeInterval TGPhotoQualityPreviewDuration = 15.0f;
} }
} error:^(id error) { } error:^(id error) {
TGLegacyLog(@"Video Quality Preview Error: %@", error); TGLegacyLog(@"Video Quality Preview Error: %@", error);
} completed:nil]]; } completed:nil file:__FILE_NAME__ line:__LINE__]];
} }
- (void)_setupPlaybackReachedEndObserver - (void)_setupPlaybackReachedEndObserver

View File

@ -1293,12 +1293,12 @@ typedef enum
- (void)capturePipelineRecordingDidStart:(TGVideoCameraPipeline *)__unused capturePipeline - (void)capturePipelineRecordingDidStart:(TGVideoCameraPipeline *)__unused capturePipeline
{ {
__weak TGVideoMessageCaptureController *weakSelf = self; __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; __strong TGVideoMessageCaptureController *strongSelf = weakSelf;
if (strongSelf != nil && strongSelf->_requestActivityHolder) { if (strongSelf != nil && strongSelf->_requestActivityHolder) {
strongSelf->_activityHolder = strongSelf->_requestActivityHolder(); strongSelf->_activityHolder = strongSelf->_requestActivityHolder();
} }
}]]; } file:__FILE_NAME__ line:__LINE__]];
} }
- (void)capturePipelineRecordingWillStop:(TGVideoCameraPipeline *)__unused capturePipeline - (void)capturePipelineRecordingWillStop:(TGVideoCameraPipeline *)__unused capturePipeline

View File

@ -404,7 +404,7 @@ static CGRect viewFrame(UIView *view)
[self addSubview:_slowmodeView]; [self addSubview:_slowmodeView];
__weak TGVideoMessageControls *weakSelf = self; __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; __strong TGVideoMessageControls *strongSelf = weakSelf;
if (strongSelf != nil) { if (strongSelf != nil) {
int32_t timestamp = (int32_t)[[NSDate date] timeIntervalSince1970]; int32_t timestamp = (int32_t)[[NSDate date] timeIntervalSince1970];

View File

@ -395,7 +395,7 @@ static id<LegacyComponentsContext> _defaultContext = nil;
_currentSizeClass = UIUserInterfaceSizeClassCompact; _currentSizeClass = UIUserInterfaceSizeClassCompact;
__weak TGViewController *weakSelf = self; __weak TGViewController *weakSelf = self;
_sizeClassDisposable = [[_context sizeClassSignal] startWithNext:^(NSNumber *next) { _sizeClassDisposable = [[_context sizeClassSignal] startStrictWithNext:^(NSNumber *next) {
__strong TGViewController *strongSelf = weakSelf; __strong TGViewController *strongSelf = weakSelf;
if (strongSelf != nil) { if (strongSelf != nil) {
if (strongSelf->_currentSizeClass != [next integerValue]) { if (strongSelf->_currentSizeClass != [next integerValue]) {
@ -405,7 +405,7 @@ static id<LegacyComponentsContext> _defaultContext = nil;
} }
} }
} }
}]; } file:__FILE_NAME__ line:__LINE__];
initializedSizeClass = true; initializedSizeClass = true;
if ([self respondsToSelector:@selector(setAutomaticallyAdjustsScrollViewInsets:)]) if ([self respondsToSelector:@selector(setAutomaticallyAdjustsScrollViewInsets:)])

View File

@ -51,12 +51,3 @@
- (MTSignal *)reduceLeft:(id)value with:(id (^)(id, id))f; - (MTSignal *)reduceLeft:(id)value with:(id (^)(id, id))f;
@end @end
@interface MTPipe : NSObject
@property (nonatomic, copy, readonly) MTSignal *(^signalProducer)();
@property (nonatomic, copy, readonly) void (^sink)(id);
- (instancetype)initWithReplay:(bool)replay;
@end

View File

@ -839,101 +839,3 @@ static dispatch_block_t recursiveBlock(void (^block)(dispatch_block_t recurse))
} }
@end @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

View File

@ -184,7 +184,7 @@ typedef enum {
_alternativeLocalization = [[SVariable alloc] init]; _alternativeLocalization = [[SVariable alloc] init];
_localizationsDisposable = [[suggestedLocalizationSignal deliverOn:[SQueue mainQueue]] startWithNext:^(TGSuggestedLocalization *next) { _localizationsDisposable = [[suggestedLocalizationSignal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(TGSuggestedLocalization *next) {
__strong RMIntroViewController *strongSelf = weakSelf; __strong RMIntroViewController *strongSelf = weakSelf;
if (strongSelf != nil && next != nil) { if (strongSelf != nil && next != nil) {
if (strongSelf->_alternativeLocalizationInfo == nil) { if (strongSelf->_alternativeLocalizationInfo == nil) {
@ -203,7 +203,7 @@ typedef enum {
} }
} }
} }
}]; } file:__FILE_NAME__ line:__LINE__];
} }
return self; return self;
} }

View File

@ -15,6 +15,9 @@ objc_library(
includes = [ includes = [
"Source", "Source",
], ],
deps = [
"//submodules/SSignalKit/SwiftSignalKit"
],
sdk_frameworks = [ sdk_frameworks = [
"Foundation", "Foundation",
], ],

View File

@ -2,11 +2,11 @@
#import <os/lock.h> #import <os/lock.h>
#import <objc/runtime.h> #import <objc/runtime.h>
#import <libkern/OSAtomic.h> #import <pthread/pthread.h>
@interface SBlockDisposable () @interface SBlockDisposable () {
{ void (^_action)();
void *_block; pthread_mutex_t _lock;
} }
@end @end
@ -18,47 +18,35 @@
self = [super init]; self = [super init];
if (self != nil) if (self != nil)
{ {
_block = (__bridge_retained void *)[block copy]; _action = [block copy];
pthread_mutex_init(&_lock, nil);
} }
return self; return self;
} }
- (void)dealloc - (void)dealloc {
{ void (^freeAction)() = nil;
void *block = _block; pthread_mutex_lock(&_lock);
if (block != NULL) freeAction = _action;
{ _action = nil;
#pragma clang diagnostic push pthread_mutex_unlock(&_lock);
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
if (OSAtomicCompareAndSwapPtr(block, 0, &_block)) if (freeAction) {
{
if (block != nil)
{
__unused __strong id strongBlock = (__bridge_transfer id)block;
strongBlock = nil;
}
}
#pragma clang diagnostic pop
} }
pthread_mutex_destroy(&_lock);
} }
- (void)dispose - (void)dispose {
{ void (^disposeAction)() = nil;
void *block = _block;
if (block != NULL) pthread_mutex_lock(&_lock);
{ disposeAction = _action;
#pragma clang diagnostic push _action = nil;
#pragma clang diagnostic ignored "-Wdeprecated-declarations" pthread_mutex_unlock(&_lock);
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
{ if (disposeAction) {
if (block != nil) disposeAction();
{
__strong id strongBlock = (__bridge_transfer id)block;
((dispatch_block_t)strongBlock)();
strongBlock = nil;
}
}
#pragma clang diagnostic pop
} }
} }

View File

@ -2,91 +2,79 @@
#import "SSignal.h" #import "SSignal.h"
#import <os/lock.h> #import <pthread/pthread.h>
@interface SDisposableSet () @interface SDisposableSet ()
{ {
os_unfair_lock _lock; pthread_mutex_t _lock;
bool _disposed; bool _disposed;
id<SDisposable> _singleDisposable; NSMutableArray<id<SDisposable>> *_disposables;
NSArray *_multipleDisposables;
} }
@end @end
@implementation SDisposableSet @implementation SDisposableSet
- (void)add:(id<SDisposable>)disposable - (instancetype)init {
{ self = [super init];
if (disposable == nil) if (self != nil) {
return; pthread_mutex_init(&_lock, nil);
_disposables = [[NSMutableArray alloc] init];
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;
}
} }
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]; [disposable dispose];
}
} }
- (void)remove:(id<SDisposable>)disposable { - (void)remove:(id<SDisposable>)disposable {
os_unfair_lock_lock(&_lock); pthread_mutex_lock(&_lock);
if (_multipleDisposables != nil) for (NSInteger i = 0; i < _disposables.count; i++) {
{ if (_disposables[i] == disposable) {
NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithArray:_multipleDisposables]; [_disposables removeObjectAtIndex:i];
[multipleDisposables removeObject:disposable]; break;
_multipleDisposables = multipleDisposables; }
} }
else if (_singleDisposable == disposable) pthread_mutex_unlock(&_lock);
{
_singleDisposable = nil;
}
os_unfair_lock_unlock(&_lock);
} }
- (void)dispose - (void)dispose {
{ NSArray<id<SDisposable>> *disposables = nil;
id<SDisposable> singleDisposable = nil; pthread_mutex_lock(&_lock);
NSArray *multipleDisposables = nil; if (!_disposed) {
os_unfair_lock_lock(&_lock);
if (!_disposed)
{
_disposed = true; _disposed = true;
singleDisposable = _singleDisposable; disposables = _disposables;
multipleDisposables = _multipleDisposables; _disposables = nil;
_singleDisposable = nil;
_multipleDisposables = nil;
} }
os_unfair_lock_unlock(&_lock); pthread_mutex_unlock(&_lock);
if (singleDisposable != nil) if (disposables) {
[singleDisposable dispose]; for (id<SDisposable> disposable in disposables) {
if (multipleDisposables != nil)
{
for (id<SDisposable> disposable in multipleDisposables)
{
[disposable dispose]; [disposable dispose];
} }
} }

View File

@ -1,10 +1,10 @@
#import "SMetaDisposable.h" #import "SMetaDisposable.h"
#import <os/lock.h> #import <pthread/pthread.h>
@interface SMetaDisposable () @interface SMetaDisposable ()
{ {
os_unfair_lock _lock; pthread_mutex_t _lock;
bool _disposed; bool _disposed;
id<SDisposable> _disposable; id<SDisposable> _disposable;
} }
@ -13,41 +13,64 @@
@implementation SMetaDisposable @implementation SMetaDisposable
- (void)setDisposable:(id<SDisposable>)disposable - (instancetype)init {
{ self = [super init];
id<SDisposable> previousDisposable = nil; if (self != nil) {
bool dispose = false; 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); if (freeDisposable) {
dispose = _disposed; }
if (!dispose)
{ 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; previousDisposable = _disposable;
_disposable = disposable; _disposable = disposable;
} }
os_unfair_lock_unlock(&_lock); pthread_mutex_unlock(&_lock);
if (previousDisposable != nil) if (previousDisposable) {
[previousDisposable dispose]; [previousDisposable dispose];
}
if (dispose) if (disposeImmediately) {
[disposable dispose]; [disposable dispose];
}
} }
- (void)dispose - (void)dispose {
{
id<SDisposable> disposable = nil; id<SDisposable> disposable = nil;
os_unfair_lock_lock(&_lock); pthread_mutex_lock(&_lock);
if (!_disposed) if (!_disposed) {
{
disposable = _disposable;
_disposed = true; _disposed = true;
disposable = _disposable;
_disposable = nil;
} }
os_unfair_lock_unlock(&_lock); pthread_mutex_unlock(&_lock);
if (disposable != nil) if (disposable) {
[disposable dispose]; [disposable dispose];
}
} }
@end @end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -157,7 +157,7 @@
{ {
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) { return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) {
SAtomic *value = [[SAtomic alloc] initWithValue:nil]; 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) { [value modify:^id(SSignal_ThrottleContainer *container) {
if (container != nil) { if (container != nil) {
if (!container.committed) { if (!container.committed) {

View File

@ -1,7 +0,0 @@
#import <SSignalKit/SSignal.h>
@interface SSignal (Multicast)
- (SSignal * _Nonnull)multicast;
@end

View File

@ -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

View File

@ -14,11 +14,11 @@
{ {
return [[SSignal alloc] initWithGenerator:^id<SDisposable> (SSubscriber *subscriber) 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) {
{ [startDisposable setDisposable:[self startWithNext:^(id next)
[disposable setDisposable:[self startWithNext:^(id next)
{ {
[subscriber putNext:next]; [subscriber putNext:next];
} error:^(id error) } error:^(id error)
@ -32,12 +32,15 @@
[timer start]; [timer start];
[disposable setDisposable:[[SBlockDisposable alloc] initWithBlock:^ [timerDisposable setDisposable:[[SBlockDisposable alloc] initWithBlock:^
{ {
[timer invalidate]; [timer invalidate];
}]]; }]];
return disposable; return [[SBlockDisposable alloc] initWithBlock:^{
[startDisposable dispose];
[timerDisposable dispose];
}];
}]; }];
} }
@ -45,11 +48,12 @@
{ {
return [[SSignal alloc] initWithGenerator:^id<SDisposable> (SSubscriber *subscriber) 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]; [subscriber putNext:next];
} error:^(id error) } error:^(id error)
@ -62,7 +66,7 @@
} queue:queue]; } queue:queue];
[timer start]; [timer start];
[disposable setDisposable:[self startWithNext:^(id next) [timerDisposable setDisposable:[self startWithNext:^(id next)
{ {
[timer invalidate]; [timer invalidate];
[subscriber putNext:next]; [subscriber putNext:next];
@ -76,7 +80,10 @@
[subscriber putCompletion]; [subscriber putCompletion];
}]]; }]];
return disposable; return [[SBlockDisposable alloc] initWithBlock:^{
[startDisposable dispose];
[timerDisposable dispose];
}];
}]; }];
} }

View File

@ -9,10 +9,13 @@
- (instancetype _Nonnull)initWithGenerator:(id<SDisposable> _Nullable (^ _Nonnull)(SSubscriber * _Nonnull))generator; - (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 error:(void (^ _Nullable)(id _Nullable error))error completed:(void (^ _Nullable)())completed;
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next; - (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;
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next completed:(void (^ _Nullable)())completed;
- (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 @end

View File

@ -2,30 +2,99 @@
#import "SBlockDisposable.h" #import "SBlockDisposable.h"
#import <pthread/pthread.h>
@interface SSubscriberDisposable : NSObject <SDisposable> @interface SSubscriberDisposable : NSObject <SDisposable>
{ {
SSubscriber *_subscriber; __weak SSubscriber *_subscriber;
id<SDisposable> _disposable; id<SDisposable> _disposable;
pthread_mutex_t _lock;
} }
@end @end
@implementation SSubscriberDisposable @implementation SSubscriberDisposable
- (instancetype)initWithSubscriber:(SSubscriber *)subscriber disposable:(id<SDisposable>)disposable - (instancetype)initWithSubscriber:(SSubscriber *)subscriber disposable:(id<SDisposable>)disposable {
{
self = [super init]; self = [super init];
if (self != nil) if (self != nil) {
{
_subscriber = subscriber; _subscriber = subscriber;
_disposable = disposable; _disposable = disposable;
pthread_mutex_init(&_lock, nil);
} }
return self; return self;
} }
- (void)dispose - (void)dealloc {
{ pthread_mutex_destroy(&_lock);
[_subscriber _markTerminatedWithoutDisposal]; }
- (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]; [_disposable dispose];
} }
@ -39,69 +108,54 @@
@implementation SSignal @implementation SSignal
- (instancetype)initWithGenerator:(id<SDisposable> (^)(SSubscriber *))generator - (instancetype)initWithGenerator:(id<SDisposable> (^)(SSubscriber *))generator {
{
self = [super init]; self = [super init];
if (self != nil) if (self != nil) {
{
_generator = [generator copy]; _generator = [generator copy];
} }
return self; return self;
} }
- (id<SDisposable>)startWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed traceName:(NSString *)traceName - (id<SDisposable>)startWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed {
{
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
{
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:error completed:completed]; SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:error completed:completed];
id<SDisposable> disposable = _generator(subscriber); id<SDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable]; [subscriber _assignDisposable:disposable];
return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable: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]; SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:nil completed:nil];
id<SDisposable> disposable = _generator(subscriber); id<SDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable]; [subscriber _assignDisposable:disposable];
return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable: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]; SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:nil completed:completed];
id<SDisposable> disposable = _generator(subscriber); id<SDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable]; [subscriber _assignDisposable:disposable];
return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable]; return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
} }
- (SSignal *)trace:(NSString *)name - (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];
#ifdef DEBUG id<SDisposable> disposable = _generator(subscriber);
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) [subscriber _assignDisposable:disposable];
{ return [[SStrictDisposable alloc] initWithDisposable:[[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable] file:file line:line];
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
} }
@end @end

View File

@ -22,9 +22,7 @@ FOUNDATION_EXPORT const unsigned char SSignalKitVersionString[];
#import <SSignalKit/SMetaDisposable.h> #import <SSignalKit/SMetaDisposable.h>
#import <SSignalKit/SSignal+Single.h> #import <SSignalKit/SSignal+Single.h>
#import <SSignalKit/SSignal+Mapping.h> #import <SSignalKit/SSignal+Mapping.h>
#import <SSignalKit/SSignal+Multicast.h>
#import <SSignalKit/SSignal+Meta.h> #import <SSignalKit/SSignal+Meta.h>
#import <SSignalKit/SSignal+Accumulate.h>
#import <SSignalKit/SSignal+Dispatch.h> #import <SSignalKit/SSignal+Dispatch.h>
#import <SSignalKit/SSignal+Catch.h> #import <SSignalKit/SSignal+Catch.h>
#import <SSignalKit/SSignal+SideEffects.h> #import <SSignalKit/SSignal+SideEffects.h>
@ -32,7 +30,6 @@ FOUNDATION_EXPORT const unsigned char SSignalKitVersionString[];
#import <SSignalKit/SSignal+Timing.h> #import <SSignalKit/SSignal+Timing.h>
#import <SSignalKit/SSignal+Take.h> #import <SSignalKit/SSignal+Take.h>
#import <SSignalKit/SSignal+Pipe.h> #import <SSignalKit/SSignal+Pipe.h>
#import <SSignalKit/SMulticastSignalManager.h>
#import <SSignalKit/STimer.h> #import <SSignalKit/STimer.h>
#import <SSignalKit/SVariable.h> #import <SSignalKit/SVariable.h>
#import <SSignalKit/SQueueLocalObject.h> #import <SSignalKit/SQueueLocalObject.h>

View File

@ -65,6 +65,7 @@
- (void)_markTerminatedWithoutDisposal - (void)_markTerminatedWithoutDisposal
{ {
id<SDisposable> disposable = nil;
os_unfair_lock_lock(&_lock); os_unfair_lock_lock(&_lock);
SSubscriberBlocks *blocks = nil; SSubscriberBlocks *blocks = nil;
if (!_terminated) if (!_terminated)
@ -74,11 +75,16 @@
_terminated = true; _terminated = true;
} }
disposable = _disposable;
_disposable = nil;
os_unfair_lock_unlock(&_lock); os_unfair_lock_unlock(&_lock);
if (blocks) { if (blocks) {
blocks = nil; blocks = nil;
} }
if (disposable) {
disposable = nil;
}
} }
- (void)putNext:(id)next - (void)putNext:(id)next
@ -116,8 +122,10 @@
blocks->_error(error); blocks->_error(error);
} }
if (shouldDispose) if (shouldDispose) {
[self->_disposable dispose]; [self->_disposable dispose];
self->_disposable = nil;
}
} }
- (void)putCompletion - (void)putCompletion
@ -139,13 +147,16 @@
if (blocks && blocks->_completed) if (blocks && blocks->_completed)
blocks->_completed(); blocks->_completed();
if (shouldDispose) if (shouldDispose) {
[self->_disposable dispose]; [self->_disposable dispose];
self->_disposable = nil;
}
} }
- (void)dispose - (void)dispose
{ {
[self->_disposable dispose]; [self->_disposable dispose];
self->_disposable = nil;
} }
@end @end

View File

@ -4,8 +4,8 @@
@interface STimer : NSObject @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:(void (^ _Nonnull)(STimer * _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 nativeQueue:(dispatch_queue_t _Nonnull)nativeQueue;
- (void)start; - (void)start;
- (void)invalidate; - (void)invalidate;

View File

@ -8,7 +8,7 @@
NSTimeInterval _timeout; NSTimeInterval _timeout;
NSTimeInterval _timeoutDate; NSTimeInterval _timeoutDate;
bool _repeat; bool _repeat;
dispatch_block_t _completion; void (^_completion)(STimer * _Nonnull);
dispatch_queue_t _nativeQueue; dispatch_queue_t _nativeQueue;
} }
@ -16,11 +16,11 @@
@implementation STimer @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]; 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]; self = [super init];
if (self != nil) if (self != nil)
@ -54,7 +54,7 @@
dispatch_source_set_event_handler(_timer, ^ dispatch_source_set_event_handler(_timer, ^
{ {
if (_completion) if (_completion)
_completion(); _completion(self);
if (!_repeat) if (!_repeat)
[self invalidate]; [self invalidate];
}); });
@ -64,7 +64,7 @@
- (void)fireAndInvalidate - (void)fireAndInvalidate
{ {
if (_completion) if (_completion)
_completion(); _completion(self);
[self invalidate]; [self invalidate];
} }

View File

@ -107,7 +107,7 @@ public final class StoryContentContextImpl: StoryContentContext {
return (views, peers, globalNotificationSettings, allEntityFiles) 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 { guard let self else {
return return
} }
@ -384,7 +384,7 @@ public final class StoryContentContextImpl: StoryContentContext {
self.nextPeerContext = nextPeerContext self.nextPeerContext = nextPeerContext
self.centralDisposable = (centralPeerContext.updated.get() self.centralDisposable = (centralPeerContext.updated.get()
|> deliverOnMainQueue).start(next: { [weak self] _ in |> deliverOnMainQueue).startStrict(next: { [weak self] _ in
guard let self else { guard let self else {
return return
} }
@ -393,7 +393,7 @@ public final class StoryContentContextImpl: StoryContentContext {
if let previousPeerContext { if let previousPeerContext {
self.previousDisposable = (previousPeerContext.updated.get() self.previousDisposable = (previousPeerContext.updated.get()
|> deliverOnMainQueue).start(next: { [weak self] _ in |> deliverOnMainQueue).startStrict(next: { [weak self] _ in
guard let self else { guard let self else {
return return
} }
@ -403,7 +403,7 @@ public final class StoryContentContextImpl: StoryContentContext {
if let nextPeerContext { if let nextPeerContext {
self.nextDisposable = (nextPeerContext.updated.get() self.nextDisposable = (nextPeerContext.updated.get()
|> deliverOnMainQueue).start(next: { [weak self] _ in |> deliverOnMainQueue).startStrict(next: { [weak self] _ in
guard let self else { guard let self else {
return return
} }
@ -493,7 +493,7 @@ public final class StoryContentContextImpl: StoryContentContext {
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: focusedPeerId)), context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: focusedPeerId)),
singlePeerListContext.state singlePeerListContext.state
) )
|> deliverOnMainQueue).start(next: { [weak self] peer, state in |> deliverOnMainQueue).startStrict(next: { [weak self] peer, state in
guard let self, let peer else { guard let self, let peer else {
return return
} }
@ -587,7 +587,7 @@ public final class StoryContentContextImpl: StoryContentContext {
}) })
} else { } else {
self.storySubscriptionsDisposable = (context.engine.messages.storySubscriptions(isHidden: isHidden, tempKeepNewlyArchived: true) 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 { guard let self else {
return return
} }
@ -689,6 +689,8 @@ public final class StoryContentContextImpl: StoryContentContext {
disposable.dispose() disposable.dispose()
} }
self.storySubscriptionsDisposable?.dispose() self.storySubscriptionsDisposable?.dispose()
self.currentStateUpdatedDisposable?.dispose()
self.pendingStateReadyDisposable?.dispose()
} }
private func updatePeerContexts() { private func updatePeerContexts() {
@ -721,7 +723,7 @@ public final class StoryContentContextImpl: StoryContentContext {
} }
} }
for (peerId, ids) in idsByPeerId { 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.pendingState = pendingState
self.pendingStateReadyDisposable = (pendingState.updated.get() 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 { guard let self, let pendingState, self.pendingState === pendingState, pendingState.isReady else {
return return
} }
@ -785,7 +787,7 @@ public final class StoryContentContextImpl: StoryContentContext {
self.currentStateUpdatedDisposable?.dispose() self.currentStateUpdatedDisposable?.dispose()
self.currentStateUpdatedDisposable = (pendingState.updated.get() 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 { guard let self, let pendingState, self.currentState === pendingState else {
return return
} }
@ -864,7 +866,7 @@ public final class StoryContentContextImpl: StoryContentContext {
for (id, info) in resultResources.sorted(by: { $0.value.priority < $1.value.priority }) { for (id, info) in resultResources.sorted(by: { $0.value.priority < $1.value.priority }) {
validIds.append(id) validIds.append(id)
if self.preloadStoryResourceDisposables[id] == nil { 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 (peerId, ids) in pollIdByPeerId {
for id in ids { for id in ids {
if self.pollStoryMetadataDisposables[StoryId(peerId: peerId, id: id)] == nil { 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) { public func markAsSeen(id: StoryId) {
if !self.context.sharedContext.immediateExperimentalUISettings.skipReadHistory { 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 { guard let self else {
return return
} }
@ -1063,7 +1065,7 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
if !self.requestedStoryKeys.contains(storyKey) { if !self.requestedStoryKeys.contains(storyKey) {
self.requestedStoryKeys.insert(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) { public func markAsSeen(id: StoryId) {
if self.readGlobally { if self.readGlobally {
if !self.context.sharedContext.immediateExperimentalUISettings.skipReadHistory { 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, listContext.state,
self.focusedIdUpdated.get() self.focusedIdUpdated.get()
) )
|> deliverOnMainQueue).start(next: { [weak self] data, state, _ in |> deliverOnMainQueue).startStrict(next: { [weak self] data, state, _ in
guard let self else { guard let self else {
return return
} }
@ -1391,7 +1393,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
if let mediaId = info.media.id { if let mediaId = info.media.id {
validIds.append(mediaId) validIds.append(mediaId)
if self.preloadStoryResourceDisposables[mediaId] == nil { 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 { 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) { public func markAsSeen(id: StoryId) {
if !self.context.sharedContext.immediateExperimentalUISettings.skipReadHistory { 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()
} }
} }
} }

View File

@ -605,7 +605,7 @@ public final class StoryItemSetContainerComponent: Component {
self.addGestureRecognizer(viewListSwipeRecognizer) self.addGestureRecognizer(viewListSwipeRecognizer)
self.audioRecorderDisposable = (self.sendMessageContext.audioRecorder.get() self.audioRecorderDisposable = (self.sendMessageContext.audioRecorder.get()
|> deliverOnMainQueue).start(next: { [weak self] audioRecorder in |> deliverOnMainQueue).startStrict(next: { [weak self] audioRecorder in
guard let self else { guard let self else {
return return
} }
@ -624,7 +624,7 @@ public final class StoryItemSetContainerComponent: Component {
} }
audioRecorder.start() audioRecorder.start()
self.audioRecorderStatusDisposable = (audioRecorder.recordingState self.audioRecorderStatusDisposable = (audioRecorder.recordingState
|> deliverOnMainQueue).start(next: { [weak self] value in |> deliverOnMainQueue).startStrict(next: { [weak self] value in
guard let self else { guard let self else {
return return
} }
@ -639,7 +639,7 @@ public final class StoryItemSetContainerComponent: Component {
}) })
self.videoRecorderDisposable = (self.sendMessageContext.videoRecorder.get() self.videoRecorderDisposable = (self.sendMessageContext.videoRecorder.get()
|> deliverOnMainQueue).start(next: { [weak self] videoRecorder in |> deliverOnMainQueue).startStrict(next: { [weak self] videoRecorder in
guard let self else { guard let self else {
return return
} }
@ -703,6 +703,7 @@ public final class StoryItemSetContainerComponent: Component {
self.audioRecorderDisposable?.dispose() self.audioRecorderDisposable?.dispose()
self.audioRecorderStatusDisposable?.dispose() self.audioRecorderStatusDisposable?.dispose()
self.audioRecorderStatusDisposable?.dispose() self.audioRecorderStatusDisposable?.dispose()
self.videoRecorderDisposable?.dispose()
} }
func allowsExternalGestures(point: CGPoint) -> Bool { func allowsExternalGestures(point: CGPoint) -> Bool {
@ -2473,7 +2474,7 @@ public final class StoryItemSetContainerComponent: Component {
self.updateIsProgressPaused() self.updateIsProgressPaused()
component.controller()?.present(tooltipScreen, in: .current) 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() { func saveDraft() {
@ -3270,7 +3271,7 @@ public final class StoryItemSetContainerComponent: Component {
TelegramEngine.EngineData.Item.Peer.IsContact(id: peer.id), TelegramEngine.EngineData.Item.Peer.IsContact(id: peer.id),
TelegramEngine.EngineData.Item.Peer.IsBlocked(id: peer.id), TelegramEngine.EngineData.Item.Peer.IsBlocked(id: peer.id),
TelegramEngine.EngineData.Item.Peer.IsBlockedFromStories(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) let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
var itemList: [ContextMenuItem] = [] var itemList: [ContextMenuItem] = []
@ -3289,7 +3290,7 @@ public final class StoryItemSetContainerComponent: Component {
}, action: { [weak self] _, f in }, action: { [weak self] _, f in
f(.default) f(.default)
let _ = component.blockedPeers?.remove(peerId: peer.id).start() let _ = component.blockedPeers?.remove(peerId: peer.id).startStandalone()
guard let self else { guard let self else {
return return
@ -3311,7 +3312,7 @@ public final class StoryItemSetContainerComponent: Component {
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Stories"), color: theme.contextMenu.primaryColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Stories"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in }, action: { [weak self] _, f in
f(.default) f(.default)
let _ = component.blockedPeers?.add(peerId: peer.id).start() let _ = component.blockedPeers?.add(peerId: peer.id).startStandalone()
guard let self else { guard let self else {
return return
@ -3335,7 +3336,7 @@ public final class StoryItemSetContainerComponent: Component {
}, action: { [weak self] _, f in }, action: { [weak self] _, f in
f(.default) 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 { guard let self else {
return return
@ -3368,7 +3369,7 @@ public final class StoryItemSetContainerComponent: Component {
return false return false
} }
if case .undo = action { 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 return false
} }
@ -3382,7 +3383,7 @@ public final class StoryItemSetContainerComponent: Component {
}, action: { [weak self] _, f in }, action: { [weak self] _, f in
f(.default) 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 { guard let self else {
return return
@ -3412,7 +3413,7 @@ public final class StoryItemSetContainerComponent: Component {
return false return false
} }
if case .undo = action { 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 return false
} }
@ -4295,7 +4296,7 @@ public final class StoryItemSetContainerComponent: Component {
if self.displayLikeReactions { if self.displayLikeReactions {
if component.slice.item.storyItem.myReaction == updateReaction.reaction { 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.displayLikeReactions = false
self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut))) self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut)))
} else { } else {
@ -4306,12 +4307,12 @@ public final class StoryItemSetContainerComponent: Component {
self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut))) self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut)))
self.waitingForReactionAnimateOutToLike = updateReaction.reaction 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 { } else {
let _ = (component.context.engine.stickers.availableReactions() let _ = (component.context.engine.stickers.availableReactions()
|> take(1) |> 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 { guard let self, let component = self.component, let availableReactions else {
return return
} }
@ -4401,7 +4402,7 @@ public final class StoryItemSetContainerComponent: Component {
let peer = component.slice.peer let peer = component.slice.peer
let _ = (enqueueMessages(account: context.account, peerId: peer.id, messages: [message]) 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 { if let animation, let self, let component = self.component {
let controller = UndoOverlayController( let controller = UndoOverlayController(
presentationData: presentationData, presentationData: presentationData,
@ -4771,7 +4772,7 @@ public final class StoryItemSetContainerComponent: Component {
closeFriends: component.closeFriends.get(), closeFriends: component.closeFriends.get(),
blockedPeersContext: component.blockedPeers 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 { guard let self else {
return return
} }
@ -4788,7 +4789,7 @@ public final class StoryItemSetContainerComponent: Component {
self.updateIsProgressPaused() self.updateIsProgressPaused()
return 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) self.presentPrivacyTooltip(privacy: privacy)
@ -4852,7 +4853,7 @@ public final class StoryItemSetContainerComponent: Component {
initialPeerIds: Set(privacy.additionallyIncludePeers), initialPeerIds: Set(privacy.additionallyIncludePeers),
blockedPeersContext: component.blockedPeers 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 { guard let self else {
return return
} }
@ -4865,10 +4866,10 @@ public final class StoryItemSetContainerComponent: Component {
return return
} }
if blockedPeers, let blockedPeers = self?.component?.blockedPeers { if blockedPeers, let blockedPeers = self?.component?.blockedPeers {
let _ = blockedPeers.updatePeerIds(result.additionallyIncludePeers).start() let _ = blockedPeers.updatePeerIds(result.additionallyIncludePeers).startStandalone()
completion(privacy) completion(privacy)
} else if case .closeFriends = privacy.base { } 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 { if let component = self?.component {
component.closeFriends.set(.single(peers)) component.closeFriends.set(.single(peers))
} }
@ -5096,7 +5097,7 @@ public final class StoryItemSetContainerComponent: Component {
if let imageData = compressImageToJPEG(image, quality: 0.7) { 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) 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 { guard let self else {
return 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) 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 { guard let self else {
return return
} }
@ -5170,7 +5171,7 @@ public final class StoryItemSetContainerComponent: Component {
} }
} else if updatedText != nil { } else if updatedText != nil {
let _ = (context.engine.messages.editStory(peerId: peerId, id: id, media: nil, mediaAreas: nil, text: updatedText, entities: updatedEntities, privacy: 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 { switch result {
case .completed: case .completed:
Queue.mainQueue().after(0.1) { Queue.mainQueue().after(0.1) {
@ -5414,7 +5415,7 @@ public final class StoryItemSetContainerComponent: Component {
return 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 { if component.slice.item.storyItem.myReaction != nil {
return return
@ -5701,7 +5702,7 @@ public final class StoryItemSetContainerComponent: Component {
return 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) let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
if component.slice.item.storyItem.isPinned { 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) 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 { guard let self, let component = self.component else {
return return
} }
@ -5852,7 +5853,7 @@ public final class StoryItemSetContainerComponent: Component {
return 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) let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
if component.slice.item.storyItem.isPinned { 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) 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 { guard let self, let component = self.component else {
return return
} }
@ -6053,7 +6054,7 @@ public final class StoryItemSetContainerComponent: Component {
return translationSettings return translationSettings
} }
let _ = combineLatest( let _ = (combineLatest(
queue: Queue.mainQueue(), queue: Queue.mainQueue(),
component.context.engine.data.get( component.context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: component.slice.peer.id), 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) TelegramEngine.EngineData.Item.Peer.Peer(id: component.context.account.peerId)
), ),
translationSettings 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 { guard let self, let component = self.component, let controller = component.controller() else {
return return
} }
@ -6091,7 +6093,7 @@ public final class StoryItemSetContainerComponent: Component {
return 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 iconColor = UIColor.white
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme) 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) 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 { guard let self, let component = self.component else {
return return
} }
@ -6302,7 +6304,7 @@ public final class StoryItemSetContainerComponent: Component {
guard let self, let component = self.component, let controller = component.controller(), let reason else { guard let self, let component = self.component, let controller = component.controller(), let reason else {
return 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( controller.present(
UndoOverlayController( UndoOverlayController(
presentationData: presentationData, presentationData: presentationData,
@ -6376,7 +6378,7 @@ public final class StoryItemSetContainerComponent: Component {
let _ = (ApplicationSpecificNotice.displayStoryUnmuteTooltip(accountManager: component.context.sharedContext.accountManager) let _ = (ApplicationSpecificNotice.displayStoryUnmuteTooltip(accountManager: component.context.sharedContext.accountManager)
|> delay(0.3, queue: .mainQueue()) |> 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 { guard let self, let component = self.component else {
return return
} }
@ -6390,7 +6392,7 @@ public final class StoryItemSetContainerComponent: Component {
) )
component.controller()?.present(tooltipScreen, in: .current) component.controller()?.present(tooltipScreen, in: .current)
let _ = ApplicationSpecificNotice.setDisplayStoryUnmuteTooltip(accountManager: component.context.sharedContext.accountManager).start() let _ = ApplicationSpecificNotice.setDisplayStoryUnmuteTooltip(accountManager: component.context.sharedContext.accountManager).startStandalone()
} }
}) })
} }

View File

@ -231,7 +231,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
let hasActiveAudioSession = Promise<Bool>(false) let hasActiveAudioSession = Promise<Bool>(false)
private let sharedContextPromise = Promise<SharedApplicationContext>() private let sharedContextPromise = Promise<SharedApplicationContext>()
private let watchCommunicationManagerPromise = Promise<WatchCommunicationManager?>() //private let watchCommunicationManagerPromise = Promise<WatchCommunicationManager?>()
private var accountManager: AccountManager<TelegramAccountManagerTypes>? private var accountManager: AccountManager<TelegramAccountManagerTypes>?
private var accountManagerState: AccountManagerState? private var accountManagerState: AccountManagerState?
@ -973,7 +973,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
return .single(nil) return .single(nil)
} }
} }
let watchTasks = self.context.get() /*let watchTasks = self.context.get()
|> mapToSignal { context -> Signal<AccountRecordId?, NoError> in |> mapToSignal { context -> Signal<AccountRecordId?, NoError> in
if let context = context, let watchManager = context.context.watchManager { if let context = context, let watchManager = context.context.watchManager {
let accountId = context.context.account.id let accountId = context.context.account.id
@ -992,7 +992,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
} else { } else {
return .single(nil) return .single(nil)
} }
} }*/
let wakeupManager = SharedWakeupManager(beginBackgroundTask: { name, expiration in let wakeupManager = SharedWakeupManager(beginBackgroundTask: { name, expiration in
let id = application.beginBackgroundTask(withName: name, expirationHandler: expiration) let id = application.beginBackgroundTask(withName: name, expirationHandler: expiration)
Logger.shared.log("App \(self.episodeId)", "Begin background task \(name): \(id)") Logger.shared.log("App \(self.episodeId)", "Begin background task \(name): \(id)")
@ -1004,7 +1004,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
application.endBackgroundTask(id) application.endBackgroundTask(id)
}, backgroundTimeRemaining: { application.backgroundTimeRemaining }, acquireIdleExtension: { }, backgroundTimeRemaining: { application.backgroundTimeRemaining }, acquireIdleExtension: {
return applicationBindings.pushIdleTimerExtension() 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) return sharedContext.accountUserInterfaceInUse(id)
}) })
let sharedApplicationContext = SharedApplicationContext(sharedContext: sharedContext, notificationManager: notificationManager, wakeupManager: wakeupManager) let sharedApplicationContext = SharedApplicationContext(sharedContext: sharedContext, notificationManager: notificationManager, wakeupManager: wakeupManager)
@ -1023,7 +1023,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
return .single(sharedApplicationContext) return .single(sharedApplicationContext)
}) })
let watchManagerArgumentsPromise = Promise<WatchManagerArguments?>() //let watchManagerArgumentsPromise = Promise<WatchManagerArguments?>()
self.context.set(self.sharedContextPromise.get() self.context.set(self.sharedContextPromise.get()
|> deliverOnMainQueue |> deliverOnMainQueue
@ -1062,7 +1062,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|> deliverOnMainQueue |> deliverOnMainQueue
|> map { accountAndSettings -> AuthorizedApplicationContext? in |> map { accountAndSettings -> AuthorizedApplicationContext? in
return accountAndSettings.flatMap { context, callListSettings 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() let _ = (self.context.get()
|> take(1) |> take(1)
|> deliverOnMainQueue).start(next: { context in |> deliverOnMainQueue).start(next: { context in
@ -1305,7 +1305,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
}).start() }).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() let _ = (self.sharedContextPromise.get()
|> take(1)).start(next: { sharedContext in |> take(1)).start(next: { sharedContext in
sharedContext.wakeupManager.allowBackgroundTimeExtension(timeout: timeout) sharedContext.wakeupManager.allowBackgroundTimeExtension(timeout: timeout)
@ -1317,7 +1317,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
} else { } else {
watchManagerArgumentsPromise.set(.single(nil)) watchManagerArgumentsPromise.set(.single(nil))
} }
}) })*/
self.resetBadge() self.resetBadge()

View File

@ -316,7 +316,7 @@
{ {
[_signalManager startSignalForKey:[NSString stringWithFormat:@"%lld", subscription.identifier] producer:^SSignal * [_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); os_unfair_lock_lock(&_replyHandlerMapLock);
void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)]; void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)];