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);
NSDictionary *cancelDict = [NSDictionary dictionaryWithObjectsAndKeys:path, @"path", [NSNumber numberWithInt:0], @"type", nil];
STimer *timer = [[STimer alloc] initWithTimeout:cancelTimeout repeat:false completion:^
{
STimer *timer = [[STimer alloc] initWithTimeout:cancelTimeout repeat:false completion:^(__unused STimer *timer) {
[self performCancelRequest:cancelDict];
} nativeQueue:[ActionStageInstance() globalStageDispatchQueue]];

View File

@ -96,7 +96,7 @@
[self setChecked:[self.selectionContext isItemSelected:(id<TGMediaSelectableItem>)asset] animated:false];
__weak TGAttachmentAssetCell *weakSelf = self;
[_itemSelectedDisposable setDisposable:[[self.selectionContext itemInformativeSelectedSignal:(id<TGMediaSelectableItem>)asset] startWithNext:^(TGMediaSelectionChange *next)
[_itemSelectedDisposable setDisposable:[[self.selectionContext itemInformativeSelectedSignal:(id<TGMediaSelectableItem>)asset] startStrictWithNext:^(TGMediaSelectionChange *next)
{
__strong TGAttachmentAssetCell *strongSelf = weakSelf;
if (strongSelf == nil)
@ -104,7 +104,7 @@
if (next.sender != strongSelf->_checkButton)
[strongSelf setChecked:next.selected animated:next.animated];
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
if (_asset == nil)

View File

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

View File

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

View File

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

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)];
} queue:[SQueue concurrentDefaultQueue]];
[progressTimer start];

View File

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

View File

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

View File

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

View File

@ -104,7 +104,7 @@
__weak TGMediaGroupsController *weakSelf = self;
_groupsDisposable = [[SMetaDisposable alloc] init];
[_groupsDisposable setDisposable:[[[_assetsLibrary assetGroups] deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *next)
[_groupsDisposable setDisposable:[[[_assetsLibrary assetGroups] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSArray *next)
{
__strong TGMediaGroupsController *strongSelf = weakSelf;
if (strongSelf == nil)
@ -131,7 +131,7 @@
if (![next containsObject:pickerController.assetGroup])
[strongSelf.navigationController popToRootViewControllerAnimated:false];
}
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
- (void)viewWillAppear:(BOOL)animated

View File

@ -80,7 +80,7 @@
__weak TGMediaPickerCell *weakSelf = self;
[self setChecked:[self.selectionContext isItemSelected:(id<TGMediaSelectableItem>)item] animated:false];
[_itemSelectedDisposable setDisposable:[[self.selectionContext itemInformativeSelectedSignal:(id<TGMediaSelectableItem>)item] startWithNext:^(TGMediaSelectionChange *next)
[_itemSelectedDisposable setDisposable:[[self.selectionContext itemInformativeSelectedSignal:(id<TGMediaSelectableItem>)item] startStrictWithNext:^(TGMediaSelectionChange *next)
{
__strong TGMediaPickerCell *strongSelf = weakSelf;
if (strongSelf == nil)
@ -88,7 +88,7 @@
if (next.sender != strongSelf->_checkButton)
[strongSelf setChecked:next.selected animated:next.animated];
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
if (_item == nil)

View File

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

View File

@ -215,7 +215,7 @@
}];
SSignal *adjustmentsSignal = [item.editingContext adjustmentsSignalForItem:item.editableMediaItem];
[_adjustmentsDisposable setDisposable:[[adjustmentsSignal deliverOn:[SQueue mainQueue]] startWithNext:^(__unused id<TGMediaEditAdjustments> next)
[_adjustmentsDisposable setDisposable:[[adjustmentsSignal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(__unused id<TGMediaEditAdjustments> next)
{
__strong TGMediaPickerGalleryPhotoItemView *strongSelf = weakSelf;
if (strongSelf == nil)
@ -223,7 +223,7 @@
[strongSelf layoutEntities];
[strongSelf->_entitiesView setupWithEntitiesData:next.paintingData.entitiesData];
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
if (item.immediateThumbnailImage != nil)
@ -249,7 +249,7 @@
}]];
if (!item.asFile) {
[_facesDisposable setDisposable:[[TGPaintFaceDetector detectFacesInItem:item.editableMediaItem editingContext:item.editingContext] startWithNext:nil]];
[_facesDisposable setDisposable:[[TGPaintFaceDetector detectFacesInItem:item.editableMediaItem editingContext:item.editingContext] startStrictWithNext:nil file:__FILE_NAME__ line:__LINE__]];
return;
}
@ -261,7 +261,7 @@
if ([item.asset isKindOfClass:[TGMediaAsset class]])
{
[_attributesDisposable setDisposable:[[[TGMediaAssetImageSignals fileAttributesForAsset:(TGMediaAsset *)item.asset] deliverOn:[SQueue mainQueue]] startWithNext:^(TGMediaAssetImageFileAttributes *next)
[_attributesDisposable setDisposable:[[[TGMediaAssetImageSignals fileAttributesForAsset:(TGMediaAsset *)item.asset] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(TGMediaAssetImageFileAttributes *next)
{
__strong TGMediaPickerGalleryPhotoItemView *strongSelf = weakSelf;
if (strongSelf == nil)
@ -276,7 +276,7 @@
} else {
strongSelf->_fileInfoLabel.text = dimensions;
}
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
}
}

View File

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

View File

@ -354,7 +354,7 @@
[self setProgressVisible:true value:0.027 animated:true];
__weak TGMediaPickerGalleryVideoItemView *weakSelf = self;
[_downloadDisposable setDisposable:[[[TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)self.item.asset allowNetworkAccess:true] deliverOn:[SQueue mainQueue]] startWithNext:^(id next)
[_downloadDisposable setDisposable:[[[TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)self.item.asset allowNetworkAccess:true] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id next)
{
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil)
@ -379,7 +379,7 @@
strongSelf->_downloaded = true;
if (strongSelf->_currentAvailabilityObserver != nil)
strongSelf->_currentAvailabilityObserver(true);
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
- (id<TGModernGalleryItem>)item {
@ -413,7 +413,7 @@
[self _playerCleanup];
if (!item.asFile) {
[_facesDisposable setDisposable:[[TGPaintFaceDetector detectFacesInItem:item.editableMediaItem editingContext:item.editingContext] startWithNext:nil]];
[_facesDisposable setDisposable:[[TGPaintFaceDetector detectFacesInItem:item.editableMediaItem editingContext:item.editingContext] startStrictWithNext:nil file:__FILE_NAME__ line:__LINE__]];
}
}
@ -489,7 +489,7 @@
SSignal *adjustmentsSignal = [[self editableItemSignal] mapToSignal:^SSignal *(id<TGMediaEditableItem> editableItem) {
return [item.editingContext adjustmentsSignalForItem:editableItem];
}];
[_adjustmentsDisposable setDisposable:[[adjustmentsSignal deliverOn:[SQueue mainQueue]] startWithNext:^(id<TGMediaEditAdjustments> adjustments)
[_adjustmentsDisposable setDisposable:[[adjustmentsSignal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id<TGMediaEditAdjustments> adjustments)
{
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil)
@ -512,7 +512,7 @@
if (!strongSelf.isPlaying) {
[strongSelf->_photoEditor reprocess];
}
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
else
{
@ -532,7 +532,7 @@
}
_fileInfoLabel.text = nil;
[_attributesDisposable setDisposable:[[[TGMediaAssetImageSignals fileAttributesForAsset:asset] deliverOn:[SQueue mainQueue]] startWithNext:^(TGMediaAssetImageFileAttributes *next)
[_attributesDisposable setDisposable:[[[TGMediaAssetImageSignals fileAttributesForAsset:asset] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(TGMediaAssetImageFileAttributes *next)
{
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil)
@ -546,7 +546,7 @@
[components addObject:[TGMediaPickerGalleryVideoItemView _stringForDimensions:next.dimensions]];
strongSelf->_fileInfoLabel.text = [components componentsJoinedByString:@" • "];
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
- (void)setIsCurrent:(bool)isCurrent
@ -576,7 +576,7 @@
__weak TGMediaPickerGalleryVideoItemView *weakSelf = self;
void (^block)(void) = ^
{
[_videoDurationDisposable setDisposable:[[_videoDurationVar.signal deliverOn:[SQueue mainQueue]] startWithNext:^(NSNumber *next)
[_videoDurationDisposable setDisposable:[[_videoDurationVar.signal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSNumber *next)
{
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil || next == nil)
@ -611,7 +611,7 @@
[strongSelf->_scrubberView resetToStart];
strongSelf->_appeared = true;
}
}]];
} file:__FILE_NAME__ line:__LINE__]];
};
if (_scrubberView.frame.size.width < FLT_EPSILON)
@ -1151,7 +1151,7 @@
}];
}
[_playerItemDisposable setDisposable:[[itemSignal deliverOn:[SQueue mainQueue]] startWithNext:^(AVPlayerItem *playerItem)
[_playerItemDisposable setDisposable:[[itemSignal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(AVPlayerItem *playerItem)
{
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil || ![playerItem isKindOfClass:[AVPlayerItem class]])
@ -1206,7 +1206,7 @@
[strongSelf positionTimerEvent];
[strongSelf _mutePlayer:strongSelf->_sendAsGif];
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)__unused change context:(void *)__unused context
@ -1682,7 +1682,7 @@
} else {
return images;
}
}] deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *images)
}] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSArray *images)
{
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf == nil)
@ -1698,7 +1698,7 @@
__strong TGMediaPickerGalleryVideoItemView *strongSelf = weakSelf;
if (strongSelf != nil)
strongSelf->_requestingThumbnails = false;
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
- (void)videoScrubberDidFinishRequestingThumbnails:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber

View File

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

View File

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

View File

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

View File

@ -661,7 +661,7 @@ static void adjustFrameRate(CAAnimation *animation) {
if (_asyncTransitionIn) {
__weak TGModernGalleryController *weakSelf = self;
self.view.hidden = true;
_transitionInDisposable = [[[[transitionFromItemView readyForTransitionIn] take:1] timeout:1.0 onQueue:[SQueue mainQueue] orSignal:[SSignal single:@true]] startWithNext:^(__unused id next) {
_transitionInDisposable = [[[[transitionFromItemView readyForTransitionIn] take:1] timeout:1.0 onQueue:[SQueue mainQueue] orSignal:[SSignal single:@true]] startStrictWithNext:^(__unused id next) {
__strong TGModernGalleryController *strongSelf = weakSelf;
if (strongSelf != nil) {
[strongSelf animateTransitionInFromView:transitionInFromView toView:transitionInToView toViewContentRect:transitionInToViewContentRect];
@ -674,7 +674,7 @@ static void adjustFrameRate(CAAnimation *animation) {
strongSelf->_startedTransitionIn();
}
}
}];
} file:__FILE_NAME__ line:__LINE__];
} else {
if (_startedTransitionIn) {
_startedTransitionIn();

View File

@ -304,7 +304,7 @@
{
__weak TGNavigationController *weakSelf = self;
[_playerStatusDisposable dispose];
_playerStatusDisposable = [[[TGNavigationBar musicPlayerProvider].musicPlayerIsActive deliverOn:[SQueue mainQueue]] startWithNext:^(NSNumber *nIsActive)
_playerStatusDisposable = [[[TGNavigationBar musicPlayerProvider].musicPlayerIsActive deliverOn:[SQueue mainQueue]] startStrictWithNext:^(NSNumber *nIsActive)
{
__strong TGNavigationController *strongSelf = weakSelf;
if (strongSelf != nil)
@ -327,7 +327,7 @@
}];
}
}
}];
} file:__FILE_NAME__ line:__LINE__];
}
else
{

View File

@ -68,7 +68,7 @@
__weak TGPassportScanView *weakSelf = self;
[_camera captureNextFrameCompletion:^(UIImage *image)
{
[_ocrDisposable setDisposable:[[[TGPassportOCR recognizeDataInImage:image shouldBeDriversLicense:false] deliverOn:[SQueue mainQueue]] startWithNext:^(TGPassportMRZ *next)
[_ocrDisposable setDisposable:[[[TGPassportOCR recognizeDataInImage:image shouldBeDriversLicense:false] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(TGPassportMRZ *next)
{
__strong TGPassportScanView *strongSelf = weakSelf;
if (strongSelf == nil)
@ -85,7 +85,7 @@
{
strongSelf->_timer = [TGTimerTarget scheduledMainThreadTimerWithTarget:self action:@selector(handleNextFrame) interval:0.45 repeat:false];
}
}]];
} file:__FILE_NAME__ line:__LINE__]];
}];
}

View File

@ -539,8 +539,7 @@ const CGFloat TGPhotoCropViewOverscreenSize = 1000;
__weak TGPhotoCropView *weakSelf = self;
_confirmTimer = [[STimer alloc] initWithTimeout:1.0f repeat:false completion:^
{
_confirmTimer = [[STimer alloc] initWithTimeout:1.0f repeat:false completion:^(__unused STimer *timer) {
__strong TGPhotoCropView *strongSelf = weakSelf;
if (strongSelf == nil)
return;

View File

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

View File

@ -217,7 +217,7 @@
- (void)setHistogramSignal:(SSignal *)signal
{
__weak TGPhotoEditorCurvesHistogramView *weakSelf = self;
[_histogramDisposable setDisposable:[[signal deliverOn:[SQueue mainQueue]] startWithNext:^(PGPhotoHistogram *next)
[_histogramDisposable setDisposable:[[signal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(PGPhotoHistogram *next)
{
__strong TGPhotoEditorCurvesHistogramView *strongSelf = weakSelf;
if (strongSelf != nil)
@ -225,7 +225,7 @@
strongSelf->_histogram = next;
[strongSelf updateHistogram];
}
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
@synthesize interactionBegan;

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

View File

@ -1293,12 +1293,12 @@ typedef enum
- (void)capturePipelineRecordingDidStart:(TGVideoCameraPipeline *)__unused capturePipeline
{
__weak TGVideoMessageCaptureController *weakSelf = self;
[_activityDisposable setDisposable:[[[SSignal complete] delay:0.3 onQueue:[SQueue mainQueue]] startWithNext:nil error:nil completed:^{
[_activityDisposable setDisposable:[[[SSignal complete] delay:0.3 onQueue:[SQueue mainQueue]] startStrictWithNext:nil error:nil completed:^{
__strong TGVideoMessageCaptureController *strongSelf = weakSelf;
if (strongSelf != nil && strongSelf->_requestActivityHolder) {
strongSelf->_activityHolder = strongSelf->_requestActivityHolder();
}
}]];
} file:__FILE_NAME__ line:__LINE__]];
}
- (void)capturePipelineRecordingWillStop:(TGVideoCameraPipeline *)__unused capturePipeline

View File

@ -404,7 +404,7 @@ static CGRect viewFrame(UIView *view)
[self addSubview:_slowmodeView];
__weak TGVideoMessageControls *weakSelf = self;
_slowmodeTimer = [[STimer alloc] initWithTimeout:0.5 repeat:true completion:^{
_slowmodeTimer = [[STimer alloc] initWithTimeout:0.5 repeat:true completion:^(__unused STimer *timer) {
__strong TGVideoMessageControls *strongSelf = weakSelf;
if (strongSelf != nil) {
int32_t timestamp = (int32_t)[[NSDate date] timeIntervalSince1970];

View File

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

View File

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

View File

@ -839,101 +839,3 @@ static dispatch_block_t recursiveBlock(void (^block)(dispatch_block_t recurse))
}
@end
@interface MTPipeReplayState : NSObject
@property (nonatomic, readonly) bool hasReceivedValue;
@property (nonatomic, strong, readonly) id recentValue;
@end
@implementation MTPipeReplayState
- (instancetype)initWithReceivedValue:(bool)receivedValue recentValue:(id)recentValue
{
self = [super init];
if (self != nil)
{
_hasReceivedValue = receivedValue;
_recentValue = recentValue;
}
return self;
}
@end
@implementation MTPipe
- (instancetype)init
{
return [self initWithReplay:false];
}
- (instancetype)initWithReplay:(bool)replay
{
self = [super init];
if (self != nil)
{
MTAtomic *subscribers = [[MTAtomic alloc] initWithValue:[[MTBag alloc] init]];
MTAtomic *replayState = replay ? [[MTAtomic alloc] initWithValue:[[MTPipeReplayState alloc] initWithReceivedValue:false recentValue:nil]] : nil;
_signalProducer = [^MTSignal *
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber)
{
__block NSUInteger index = 0;
[subscribers with:^id(MTBag *bag)
{
index = [bag addItem:[^(id next)
{
[subscriber putNext:next];
} copy]];
return nil;
}];
if (replay)
{
[replayState with:^id(MTPipeReplayState *state)
{
if (state.hasReceivedValue)
[subscriber putNext:state.recentValue];
return nil;
}];
}
return [[MTBlockDisposable alloc] initWithBlock:^
{
[subscribers with:^id(MTBag *bag)
{
[bag removeItem:index];
return nil;
}];
}];
}];
} copy];
_sink = [^(id next)
{
NSArray *items = [subscribers with:^id(MTBag *bag)
{
return [bag copyItems];
}];
for (void (^item)(id) in items)
{
item(next);
}
if (replay)
{
[replayState modify:^id(__unused MTPipeReplayState *state)
{
return [[MTPipeReplayState alloc] initWithReceivedValue:true recentValue:next];
}];
}
} copy];
}
return self;
}
@end

View File

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

View File

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

View File

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

View File

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

View File

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

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) {
SAtomic *value = [[SAtomic alloc] initWithValue:nil];
STimer *timer = [[STimer alloc] initWithTimeout:delay repeat:false completion:^{
STimer *timer = [[STimer alloc] initWithTimeout:delay repeat:false completion:^(__unused STimer *timer) {
[value modify:^id(SSignal_ThrottleContainer *container) {
if (container != nil) {
if (!container.committed) {

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

View File

@ -9,10 +9,13 @@
- (instancetype _Nonnull)initWithGenerator:(id<SDisposable> _Nullable (^ _Nonnull)(SSubscriber * _Nonnull))generator;
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next error:(void (^ _Nullable)(id _Nullable error))error completed:(void (^ _Nullable)())completed;
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next;
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next completed:(void (^ _Nullable)())completed;
- (id<SDisposable> _Nullable)startStrictWithNext:(void (^ _Nullable)(id _Nullable next))next error:(void (^ _Nullable)(id _Nullable error))error completed:(void (^ _Nullable)())completed file:(const char * _Nonnull)file line:(int)line;
- (SSignal * _Nonnull)trace:(NSString * _Nonnull)name;
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next;
- (id<SDisposable> _Nullable)startStrictWithNext:(void (^ _Nullable)(id _Nullable next))next file:(const char * _Nonnull)file line:(int)line;
- (id<SDisposable> _Nullable)startWithNext:(void (^ _Nullable)(id _Nullable next))next completed:(void (^ _Nullable)())completed;
- (id<SDisposable> _Nullable)startStrictWithNext:(void (^ _Nullable)(id _Nullable next))next completed:(void (^ _Nullable)())completed file:(const char * _Nonnull)file line:(int)line;
@end

View File

@ -2,30 +2,99 @@
#import "SBlockDisposable.h"
#import <pthread/pthread.h>
@interface SSubscriberDisposable : NSObject <SDisposable>
{
SSubscriber *_subscriber;
__weak SSubscriber *_subscriber;
id<SDisposable> _disposable;
pthread_mutex_t _lock;
}
@end
@implementation SSubscriberDisposable
- (instancetype)initWithSubscriber:(SSubscriber *)subscriber disposable:(id<SDisposable>)disposable
{
- (instancetype)initWithSubscriber:(SSubscriber *)subscriber disposable:(id<SDisposable>)disposable {
self = [super init];
if (self != nil)
{
if (self != nil) {
_subscriber = subscriber;
_disposable = disposable;
pthread_mutex_init(&_lock, nil);
}
return self;
}
- (void)dispose
{
[_subscriber _markTerminatedWithoutDisposal];
- (void)dealloc {
pthread_mutex_destroy(&_lock);
}
- (void)dispose {
SSubscriber *subscriber = nil;
id<SDisposable> disposeItem = nil;
pthread_mutex_lock(&_lock);
disposeItem = _disposable;
_disposable = nil;
subscriber = _subscriber;
_subscriber = nil;
pthread_mutex_unlock(&_lock);
[disposeItem dispose];
[subscriber _markTerminatedWithoutDisposal];
}
@end
@interface SStrictDisposable : NSObject<SDisposable> {
id<SDisposable> _disposable;
const char *_file;
int _line;
#if DEBUG
pthread_mutex_t _lock;
bool _isDisposed;
#endif
}
- (instancetype)initWithDisposable:(id<SDisposable>)disposable file:(const char *)file line:(int)line;
- (void)dispose;
@end
@implementation SStrictDisposable
- (instancetype)initWithDisposable:(id<SDisposable>)disposable file:(const char *)file line:(int)line {
self = [super init];
if (self != nil) {
_disposable = disposable;
_file = file;
_line = line;
#if DEBUG
pthread_mutex_init(&_lock, nil);
#endif
}
return self;
}
- (void)dealloc {
#if DEBUG
pthread_mutex_lock(&_lock);
if (!_isDisposed) {
NSLog(@"Leaked disposable from %s:%d", _file, _line);
assert(false);
}
pthread_mutex_unlock(&_lock);
pthread_mutex_destroy(&_lock);
#endif
}
- (void)dispose {
pthread_mutex_lock(&_lock);
_isDisposed = true;
pthread_mutex_unlock(&_lock);
[_disposable dispose];
}
@ -39,69 +108,54 @@
@implementation SSignal
- (instancetype)initWithGenerator:(id<SDisposable> (^)(SSubscriber *))generator
{
- (instancetype)initWithGenerator:(id<SDisposable> (^)(SSubscriber *))generator {
self = [super init];
if (self != nil)
{
if (self != nil) {
_generator = [generator copy];
}
return self;
}
- (id<SDisposable>)startWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed traceName:(NSString *)traceName
{
STracingSubscriber *subscriber = [[STracingSubscriber alloc] initWithName:traceName next:next error:error completed:completed];
id<SDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable];
return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
}
- (id<SDisposable>)startWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed
{
- (id<SDisposable>)startWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed {
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:error completed:completed];
id<SDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable];
return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
}
- (id<SDisposable>)startWithNext:(void (^)(id next))next
{
- (id<SDisposable>)startStrictWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed file:(const char * _Nonnull)file line:(int)line {
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:error completed:completed];
id<SDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable];
return [[SStrictDisposable alloc] initWithDisposable:[[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable] file:file line:line];
}
- (id<SDisposable>)startWithNext:(void (^)(id next))next {
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:nil completed:nil];
id<SDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable];
return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
}
- (id<SDisposable>)startWithNext:(void (^)(id next))next completed:(void (^)())completed
{
- (id<SDisposable>)startStrictWithNext:(void (^)(id next))next file:(const char * _Nonnull)file line:(int)line {
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:nil completed:nil];
id<SDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable];
return [[SStrictDisposable alloc] initWithDisposable:[[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable] file:file line:line];
}
- (id<SDisposable>)startWithNext:(void (^)(id next))next completed:(void (^)())completed {
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:nil completed:completed];
id<SDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable];
return [[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
}
- (SSignal *)trace:(NSString *)name
{
#ifdef DEBUG
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
{
NSString *traceName = [[NSString alloc] initWithFormat:@"%@#0x%x", name, (int)random()];
NSLog(@"trace(%@ start)", traceName);
return [self startWithNext:^(id next)
{
[subscriber putNext:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[subscriber putCompletion];
} traceName:traceName];
}];
#else
return self;
#endif
- (id<SDisposable>)startStrictWithNext:(void (^)(id next))next completed:(void (^)())completed file:(const char * _Nonnull)file line:(int)line {
SSubscriber *subscriber = [[SSubscriber alloc] initWithNext:next error:nil completed:completed];
id<SDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable];
return [[SStrictDisposable alloc] initWithDisposable:[[SSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable] file:file line:line];
}
@end

View File

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

View File

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

View File

@ -4,8 +4,8 @@
@interface STimer : NSObject
- (instancetype _Nonnull)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(dispatch_block_t _Nonnull)completion queue:(SQueue * _Nonnull)queue;
- (instancetype _Nonnull)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(dispatch_block_t _Nonnull)completion nativeQueue:(dispatch_queue_t _Nonnull)nativeQueue;
- (instancetype _Nonnull)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(void (^ _Nonnull)(STimer * _Nonnull))completion queue:(SQueue * _Nonnull)queue;
- (instancetype _Nonnull)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(void (^ _Nonnull)(STimer * _Nonnull))completion nativeQueue:(dispatch_queue_t _Nonnull)nativeQueue;
- (void)start;
- (void)invalidate;

View File

@ -8,7 +8,7 @@
NSTimeInterval _timeout;
NSTimeInterval _timeoutDate;
bool _repeat;
dispatch_block_t _completion;
void (^_completion)(STimer * _Nonnull);
dispatch_queue_t _nativeQueue;
}
@ -16,11 +16,11 @@
@implementation STimer
- (id)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(dispatch_block_t)completion queue:(SQueue *)queue {
- (id)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(void (^ _Nonnull)(STimer * _Nonnull))completion queue:(SQueue *)queue {
return [self initWithTimeout:timeout repeat:repeat completion:completion nativeQueue:queue._dispatch_queue];
}
- (id)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(dispatch_block_t)completion nativeQueue:(dispatch_queue_t)nativeQueue
- (id)initWithTimeout:(NSTimeInterval)timeout repeat:(bool)repeat completion:(void (^ _Nonnull)(STimer * _Nonnull))completion nativeQueue:(dispatch_queue_t)nativeQueue
{
self = [super init];
if (self != nil)
@ -54,7 +54,7 @@
dispatch_source_set_event_handler(_timer, ^
{
if (_completion)
_completion();
_completion(self);
if (!_repeat)
[self invalidate];
});
@ -64,7 +64,7 @@
- (void)fireAndInvalidate
{
if (_completion)
_completion();
_completion(self);
[self invalidate];
}

View File

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

View File

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

View File

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

View File

@ -316,7 +316,7 @@
{
[_signalManager startSignalForKey:[NSString stringWithFormat:@"%lld", subscription.identifier] producer:^SSignal *
{
STimer *timer = [[STimer alloc] initWithTimeout:2.0 repeat:false completion:^
STimer *timer = [[STimer alloc] initWithTimeout:2.0 repeat:false completion:^(__unused STimer *timer)
{
os_unfair_lock_lock(&_replyHandlerMapLock);
void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)];