mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-17 03:40:18 +00:00
Address another round of comments
This commit is contained in:
parent
fc747ca58a
commit
f9c70470d8
@ -118,7 +118,7 @@ static NSMutableSet *__cellClassesForVisibilityNotifications = nil; // See +init
|
|||||||
_viewControllerNode.frame = self.bounds;
|
_viewControllerNode.frame = self.bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)displayNodeDidInvalidateSizeNewSize:(CGSize)newSize
|
- (void)_locked_displayNodeDidInvalidateSizeNewSize:(CGSize)newSize
|
||||||
{
|
{
|
||||||
CGSize oldSize = self.bounds.size;
|
CGSize oldSize = self.bounds.size;
|
||||||
if (CGSizeEqualToSize(oldSize, newSize) == NO) {
|
if (CGSizeEqualToSize(oldSize, newSize) == NO) {
|
||||||
|
|||||||
@ -796,7 +796,7 @@ extern NSInteger const ASDefaultDrawingPriority;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract Invalidates the current layout and begins a relayout of the node with the current `constrainedSize`. Must be called on main thread.
|
* @abstract Invalidates the layout and begins a relayout of the node with the current `constrainedSize`. Must be called on main thread.
|
||||||
*
|
*
|
||||||
* @discussion It is called right after the measurement and before -animateLayoutTransition:.
|
* @discussion It is called right after the measurement and before -animateLayoutTransition:.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -735,7 +735,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
|
|
||||||
// Perform a measurement pass to get the current layout
|
// Perform a measurement pass to get the current layout
|
||||||
// It's important to differentiate between layout and measure pass here. Calling `layoutThatFits:` just perform a
|
// It's important to differentiate between layout and measure pass here. Calling `layoutThatFits:` just perform a
|
||||||
// measure pass and no layout pass immediately. If a layout pass wold be forced via `layoutIfNeeded` it could cause an
|
// measure pass and no layout pass immediately. If a layout pass would be forced via `layoutIfNeeded` it could cause an
|
||||||
// infinite loop as in `__layout` we check if the size changed and we are just to inform the node that the size changed
|
// infinite loop as in `__layout` we check if the size changed and we are just to inform the node that the size changed
|
||||||
ASLayout *layout = [self layoutThatFits:constrainedSize];
|
ASLayout *layout = [self layoutThatFits:constrainedSize];
|
||||||
|
|
||||||
@ -743,13 +743,13 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
if (CGSizeEqualToSize(oldSize, layout.size) == NO) {
|
if (CGSizeEqualToSize(oldSize, layout.size) == NO) {
|
||||||
// If the size of the layout changes inform our container (e.g ASTableView, ASCollectionView, ASViewController, ...)
|
// If the size of the layout changes inform our container (e.g ASTableView, ASCollectionView, ASViewController, ...)
|
||||||
// that we need it to change our bounds size.
|
// that we need it to change our bounds size.
|
||||||
[self displayNodeDidInvalidateSizeNewSize:layout.size];
|
[self _locked_displayNodeDidInvalidateSizeNewSize:layout.size];
|
||||||
}
|
}
|
||||||
|
|
||||||
__instanceLock__.unlock();
|
__instanceLock__.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)displayNodeDidInvalidateSizeNewSize:(CGSize)size
|
- (void)_locked_displayNodeDidInvalidateSizeNewSize:(CGSize)size
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertThreadAffinity(self);
|
ASDisplayNodeAssertThreadAffinity(self);
|
||||||
|
|
||||||
@ -829,14 +829,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
shouldMeasureAsync:(BOOL)shouldMeasureAsync
|
shouldMeasureAsync:(BOOL)shouldMeasureAsync
|
||||||
measurementCompletion:(void(^)())completion
|
measurementCompletion:(void(^)())completion
|
||||||
{
|
{
|
||||||
if (_calculatedDisplayNodeLayout->layout == nil) {
|
|
||||||
// No measure pass happened before, it's not possible to reuse the constrained size for the transition
|
|
||||||
// Using CGSizeZero for the sizeRange can cause negative values in client layout code.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
[self transitionLayoutWithSizeRange:_calculatedDisplayNodeLayout->constrainedSize
|
[self transitionLayoutWithSizeRange:[self _locked_constrainedSizeForLayoutPass]
|
||||||
animated:animated
|
animated:animated
|
||||||
shouldMeasureAsync:shouldMeasureAsync
|
shouldMeasureAsync:shouldMeasureAsync
|
||||||
measurementCompletion:completion];
|
measurementCompletion:completion];
|
||||||
@ -848,9 +842,11 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
shouldMeasureAsync:(BOOL)shouldMeasureAsync
|
shouldMeasureAsync:(BOOL)shouldMeasureAsync
|
||||||
measurementCompletion:(void(^)())completion
|
measurementCompletion:(void(^)())completion
|
||||||
{
|
{
|
||||||
// Passed constrainedSize is the the same as the node's current constrained size it's a noop
|
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
if (_calculatedDisplayNodeLayout->isValidForConstrainedSizeParentSize(constrainedSize, constrainedSize.max)) {
|
|
||||||
|
// Check if it's a subnode in a layout transition. In this case no measurement is needed as it's part of
|
||||||
|
// the layout transition
|
||||||
|
if ([self _isInvolvedInLayoutTransition]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -859,20 +855,23 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
ASDisplayNodeAssert(ASHierarchyStateIncludesLayoutPending(_hierarchyState) == NO, @"Can't start a transition when one of the supernodes is performing one.");
|
ASDisplayNodeAssert(ASHierarchyStateIncludesLayoutPending(_hierarchyState) == NO, @"Can't start a transition when one of the supernodes is performing one.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Every new layout transition has a transition id associated to check in subsequent transitions for cancelling
|
||||||
int32_t transitionID = [self _startNewTransition];
|
int32_t transitionID = [self _startNewTransition];
|
||||||
|
|
||||||
// Move all subnodes in a pending state
|
// Move all subnodes in layout pending state for this transition
|
||||||
ASDisplayNodePerformBlockOnEverySubnode(self, NO, ^(ASDisplayNode * _Nonnull node) {
|
ASDisplayNodePerformBlockOnEverySubnode(self, NO, ^(ASDisplayNode * _Nonnull node) {
|
||||||
ASDisplayNodeAssert([node _isTransitionInProgress] == NO, @"Can't start a transition when one of the subnodes is performing one.");
|
ASDisplayNodeAssert([node _isTransitionInProgress] == NO, @"Can't start a transition when one of the subnodes is performing one.");
|
||||||
node.hierarchyState |= ASHierarchyStateLayoutPending;
|
node.hierarchyState |= ASHierarchyStateLayoutPending;
|
||||||
node.pendingTransitionID = transitionID;
|
node.pendingTransitionID = transitionID;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Transition block that executes the layout transition
|
||||||
void (^transitionBlock)(void) = ^{
|
void (^transitionBlock)(void) = ^{
|
||||||
if ([self _shouldAbortTransitionWithID:transitionID]) {
|
if ([self _shouldAbortTransitionWithID:transitionID]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform a full layout creation pass with passed in constrained size to create the new layout for the transition
|
||||||
ASLayout *newLayout;
|
ASLayout *newLayout;
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(__instanceLock__);
|
ASDN::MutexLocker l(__instanceLock__);
|
||||||
@ -905,7 +904,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update display node layout
|
// Update calculated layout
|
||||||
auto previousLayout = _calculatedDisplayNodeLayout;
|
auto previousLayout = _calculatedDisplayNodeLayout;
|
||||||
auto pendingLayout = std::make_shared<ASDisplayNodeLayout>(
|
auto pendingLayout = std::make_shared<ASDisplayNodeLayout>(
|
||||||
newLayout,
|
newLayout,
|
||||||
@ -944,6 +943,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Start transition based on flag on current or background thread
|
||||||
if (shouldMeasureAsync) {
|
if (shouldMeasureAsync) {
|
||||||
ASPerformBlockOnBackgroundThread(transitionBlock);
|
ASPerformBlockOnBackgroundThread(transitionBlock);
|
||||||
} else {
|
} else {
|
||||||
@ -971,6 +971,18 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
return _transitionInProgress;
|
return _transitionInProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)_isInvolvedInLayoutTransition
|
||||||
|
{
|
||||||
|
ASDN::MutexLocker l(__instanceLock__);
|
||||||
|
if (ASHierarchyStateIncludesLayoutPending(_hierarchyState)) {
|
||||||
|
ASLayoutElementContext context = ASLayoutElementGetCurrentContext();
|
||||||
|
if (ASLayoutElementContextIsNull(context) || _pendingTransitionID != context.transitionID) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
/// Starts a new transition and returns the transition id
|
/// Starts a new transition and returns the transition id
|
||||||
- (int32_t)_startNewTransition
|
- (int32_t)_startNewTransition
|
||||||
{
|
{
|
||||||
@ -1463,12 +1475,9 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
{
|
{
|
||||||
// Check if it's a subnode in a layout transition. In this case no measurement is needed as it's part of
|
// Check if it's a subnode in a layout transition. In this case no measurement is needed as it's part of
|
||||||
// the layout transition
|
// the layout transition
|
||||||
if (ASHierarchyStateIncludesLayoutPending(_hierarchyState)) {
|
if ([self _isInvolvedInLayoutTransition]) {
|
||||||
ASLayoutElementContext context = ASLayoutElementGetCurrentContext();
|
|
||||||
if (ASLayoutElementContextIsNull(context) || _pendingTransitionID != context.transitionID) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we can reuse the calculated display node layout. We prefer the _pendingDisplayNodeLayout over the
|
// Check if we can reuse the calculated display node layout. We prefer the _pendingDisplayNodeLayout over the
|
||||||
// _calculatedDisplayNodeLayout though
|
// _calculatedDisplayNodeLayout though
|
||||||
@ -1486,13 +1495,12 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
BOOL didCreateNewContext = NO;
|
BOOL didCreateNewContext = NO;
|
||||||
BOOL didOverrideExistingContext = NO;
|
BOOL didOverrideExistingContext = NO;
|
||||||
BOOL shouldVisualizeLayout = ASHierarchyStateIncludesVisualizeLayout(_hierarchyState);
|
BOOL shouldVisualizeLayout = ASHierarchyStateIncludesVisualizeLayout(_hierarchyState);
|
||||||
ASLayoutElementContext context;
|
ASLayoutElementContext context = ASLayoutElementGetCurrentContext();
|
||||||
if (ASLayoutElementContextIsNull(ASLayoutElementGetCurrentContext())) {
|
if (ASLayoutElementContextIsNull(context)) {
|
||||||
context = ASLayoutElementContextMake(ASLayoutElementContextDefaultTransitionID, shouldVisualizeLayout);
|
context = ASLayoutElementContextMake(ASLayoutElementContextDefaultTransitionID, shouldVisualizeLayout);
|
||||||
ASLayoutElementSetCurrentContext(context);
|
ASLayoutElementSetCurrentContext(context);
|
||||||
didCreateNewContext = YES;
|
didCreateNewContext = YES;
|
||||||
} else {
|
} else {
|
||||||
context = ASLayoutElementGetCurrentContext();
|
|
||||||
if (context.needsVisualizeNode != shouldVisualizeLayout) {
|
if (context.needsVisualizeNode != shouldVisualizeLayout) {
|
||||||
context.needsVisualizeNode = shouldVisualizeLayout;
|
context.needsVisualizeNode = shouldVisualizeLayout;
|
||||||
ASLayoutElementSetCurrentContext(context);
|
ASLayoutElementSetCurrentContext(context);
|
||||||
@ -1500,7 +1508,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out previos and pending layout for layout transition
|
// Figure out previous and pending layouts for layout transition
|
||||||
auto previousLayout = _calculatedDisplayNodeLayout;
|
auto previousLayout = _calculatedDisplayNodeLayout;
|
||||||
auto pendingLayout = [=]() -> std::shared_ptr<ASDisplayNodeLayout> {
|
auto pendingLayout = [=]() -> std::shared_ptr<ASDisplayNodeLayout> {
|
||||||
// Check if the pending display node layout can be used to transition to
|
// Check if the pending display node layout can be used to transition to
|
||||||
|
|||||||
@ -187,7 +187,7 @@ __unused static NSString * _Nonnull NSStringFromASHierarchyState(ASHierarchyStat
|
|||||||
* @abstract Subclass hook for nodes that are acting as root nodes. This method is called if one of the subnodes
|
* @abstract Subclass hook for nodes that are acting as root nodes. This method is called if one of the subnodes
|
||||||
* size is invalidated and may need to result in a different size as the current calculated size.
|
* size is invalidated and may need to result in a different size as the current calculated size.
|
||||||
*/
|
*/
|
||||||
- (void)displayNodeDidInvalidateSizeNewSize:(CGSize)newSize;
|
- (void)_locked_displayNodeDidInvalidateSizeNewSize:(CGSize)newSize;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@ -44,11 +44,14 @@ BOOL ASDisplayNodeRunRunLoopUntilBlockIsTrue(as_condition_block_t block)
|
|||||||
return passed;
|
return passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASDisplayNodeSizeToFitSize(ASDisplayNode *node, CGSize size) {
|
void ASDisplayNodeSizeToFitSize(ASDisplayNode *node, CGSize size)
|
||||||
|
{
|
||||||
CGSize sizeThatFits = [node layoutThatFits:ASSizeRangeMake(size)].size;
|
CGSize sizeThatFits = [node layoutThatFits:ASSizeRangeMake(size)].size;
|
||||||
node.bounds = (CGRect){.origin = CGPointZero, .size = sizeThatFits};
|
node.bounds = (CGRect){.origin = CGPointZero, .size = sizeThatFits};
|
||||||
}
|
}
|
||||||
void ASDisplayNodeSizeToFitSizeRange(ASDisplayNode *node, ASSizeRange sizeRange) {
|
|
||||||
|
void ASDisplayNodeSizeToFitSizeRange(ASDisplayNode *node, ASSizeRange sizeRange)
|
||||||
|
{
|
||||||
CGSize sizeThatFits = [node layoutThatFits:sizeRange].size;
|
CGSize sizeThatFits = [node layoutThatFits:sizeRange].size;
|
||||||
node.bounds = (CGRect){.origin = CGPointZero, .size = sizeThatFits};
|
node.bounds = (CGRect){.origin = CGPointZero, .size = sizeThatFits};
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user