mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 19:30:29 +00:00
Improvements for automatic range mode
- Only update range mode if visibility changes if the node is not range controlled - Only change explicitly set range mode if ASRangeController becomes visible - Return interface state for range controller in ASCollectionView and ASTableView based on if the containing node is range managed
This commit is contained in:
parent
b30fa8b2f6
commit
d3ba80ccfd
@ -918,14 +918,15 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
|||||||
- (ASInterfaceState)interfaceStateForRangeController:(ASRangeController *)rangeController
|
- (ASInterfaceState)interfaceStateForRangeController:(ASRangeController *)rangeController
|
||||||
{
|
{
|
||||||
ASCollectionNode *collectionNode = self.collectionNode;
|
ASCollectionNode *collectionNode = self.collectionNode;
|
||||||
if (collectionNode) {
|
if (collectionNode && [collectionNode supportsRangeManagedInterfaceState]) {
|
||||||
|
// Only use the interfaceStatate of nodes that are range managed
|
||||||
return collectionNode.interfaceState;
|
return collectionNode.interfaceState;
|
||||||
} else {
|
|
||||||
// Until we can always create an associated ASCollectionNode without a retain cycle,
|
|
||||||
// we might be on our own to try to guess if we're visible. The node normally
|
|
||||||
// handles this even if it is the root / directly added to the view hierarchy.
|
|
||||||
return (self.window != nil ? ASInterfaceStateVisible : ASInterfaceStateNone);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For not range managed nodes or until we can always create an associated ASCollectionNode
|
||||||
|
// without a retain cycle, we might be on our own to try to guess if we're visible. The node normally
|
||||||
|
// handles this even if it is the root / directly added to the view hierarchy.
|
||||||
|
return (self.window != nil ? ASInterfaceStateVisible : ASInterfaceStateNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths
|
- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths
|
||||||
@ -1144,9 +1145,12 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
|||||||
if (!visible && node.inHierarchy) {
|
if (!visible && node.inHierarchy) {
|
||||||
[node __exitHierarchy];
|
[node __exitHierarchy];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger updating interfaceState for cells in case ASCollectionView becomes visible or invisible
|
// Updating the visible node index paths only for range managed nodes. Not range managed nodes will get their
|
||||||
[_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:self.scrollDirection];
|
// their update in the layout pass
|
||||||
|
if (![node supportsRangeManagedInterfaceState]) {
|
||||||
|
[_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:self.scrollDirection];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - UICollectionView dead-end intercepts
|
#pragma mark - UICollectionView dead-end intercepts
|
||||||
|
|||||||
@ -1980,13 +1980,9 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
|||||||
// subclass override
|
// subclass override
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* We currently only set interface state on nodes in table/collection views. For other nodes, if they are
|
|
||||||
* in the hierarchy we enable all ASInterfaceState types with `ASInterfaceStateInHierarchy`, otherwise `None`.
|
|
||||||
*/
|
|
||||||
- (BOOL)supportsRangeManagedInterfaceState
|
- (BOOL)supportsRangeManagedInterfaceState
|
||||||
{
|
{
|
||||||
return (_hierarchyState & ASHierarchyStateRangeManaged);
|
return ASHierarchyStateIncludesRangeManaged(_hierarchyState);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASInterfaceState)interfaceState
|
- (ASInterfaceState)interfaceState
|
||||||
|
|||||||
@ -795,14 +795,15 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
|||||||
- (ASInterfaceState)interfaceStateForRangeController:(ASRangeController *)rangeController
|
- (ASInterfaceState)interfaceStateForRangeController:(ASRangeController *)rangeController
|
||||||
{
|
{
|
||||||
ASTableNode *tableNode = self.tableNode;
|
ASTableNode *tableNode = self.tableNode;
|
||||||
if (tableNode) {
|
if (tableNode && [tableNode supportsRangeManagedInterfaceState]) {
|
||||||
|
// Only use the interfaceStatate of nodes that are range managed
|
||||||
return self.tableNode.interfaceState;
|
return self.tableNode.interfaceState;
|
||||||
} else {
|
|
||||||
// Until we can always create an associated ASTableNode without a retain cycle,
|
|
||||||
// we might be on our own to try to guess if we're visible. The node normally
|
|
||||||
// handles this even if it is the root / directly added to the view hierarchy.
|
|
||||||
return (self.window != nil ? ASInterfaceStateVisible : ASInterfaceStateNone);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For not range managed nodes or until we can always create an associated ASTableNode
|
||||||
|
// without a retain cycle, we might be on our own to try to guess if we're visible. The node normally
|
||||||
|
// handles this even if it is the root / directly added to the view hierarchy.
|
||||||
|
return (self.window != nil ? ASInterfaceStateVisible : ASInterfaceStateNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - ASRangeControllerDelegate
|
#pragma mark - ASRangeControllerDelegate
|
||||||
@ -1076,9 +1077,12 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
|||||||
if (!visible && node.inHierarchy) {
|
if (!visible && node.inHierarchy) {
|
||||||
[node __exitHierarchy];
|
[node __exitHierarchy];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger updating interfaceState for cells in case ASTableView becomes visible or invisible
|
// Updating the visible node index paths only for range managed nodes. Not range managed nodes will get their
|
||||||
[_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:self.scrollDirection];
|
// their update in the layout pass
|
||||||
|
if (![node supportsRangeManagedInterfaceState]) {
|
||||||
|
[_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:self.scrollDirection];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -189,7 +189,9 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
|
|||||||
|
|
||||||
ASInterfaceState selfInterfaceState = [self interfaceState];
|
ASInterfaceState selfInterfaceState = [self interfaceState];
|
||||||
ASLayoutRangeMode rangeMode = _currentRangeMode;
|
ASLayoutRangeMode rangeMode = _currentRangeMode;
|
||||||
if (!_didUpdateCurrentRange) {
|
// If the range mode is explicitly set via updateCurrentRangeWithMode: it will last in that mode until the
|
||||||
|
// range controller becomes visible again or explicitly changes the range mode again
|
||||||
|
if (!_didUpdateCurrentRange || ASInterfaceStateIncludesVisible(selfInterfaceState)) {
|
||||||
rangeMode = [ASRangeController rangeModeForInterfaceState:selfInterfaceState currentRangeMode:_currentRangeMode];
|
rangeMode = [ASRangeController rangeModeForInterfaceState:selfInterfaceState currentRangeMode:_currentRangeMode];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +234,10 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
|
|||||||
_allPreviousIndexPaths = allCurrentIndexPaths;
|
_allPreviousIndexPaths = allCurrentIndexPaths;
|
||||||
|
|
||||||
_currentRangeMode = rangeMode;
|
_currentRangeMode = rangeMode;
|
||||||
_didUpdateCurrentRange = NO;
|
// Reset the current range mode only if the range controller comes visible
|
||||||
|
if (ASInterfaceStateIncludesVisible(selfInterfaceState)) {
|
||||||
|
_didUpdateCurrentRange = NO;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_rangeIsValid) {
|
if (!_rangeIsValid) {
|
||||||
[allIndexPaths addObjectsFromArray:ASIndexPathsForTwoDimensionalArray(allNodes)];
|
[allIndexPaths addObjectsFromArray:ASIndexPathsForTwoDimensionalArray(allNodes)];
|
||||||
|
|||||||
@ -12,6 +12,18 @@
|
|||||||
#import "ASCollectionNode.h"
|
#import "ASCollectionNode.h"
|
||||||
#import "ASTableNode.h"
|
#import "ASTableNode.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the range mode for a range controller to a specific range mode until the node that contains the range
|
||||||
|
* controller becomes visible again
|
||||||
|
*
|
||||||
|
* Logic for the automatic range mode:
|
||||||
|
* 1. If there are no visible node paths available nothing is to be done and no range update is done
|
||||||
|
* 2. The initial range update always will be ASLayoutRangeModeCount (ASLayoutRangeModeMinimum) as it's the initial fetch
|
||||||
|
* 3. If the range mode is explicitly set via updateCurrentRangeWithMode: it will last in that mode until the range controller becomes visible and a new range update was triggered or a new range mode via updateCurrentRangeWithMode: is set
|
||||||
|
* 4. If range mode is not explicitly set the range mode is variying based if the range controller is visible or not
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@protocol ASRangeControllerUpdateRangeProtocol <NSObject>
|
@protocol ASRangeControllerUpdateRangeProtocol <NSObject>
|
||||||
|
|
||||||
|
|||||||
@ -56,6 +56,11 @@ inline BOOL ASHierarchyStateIncludesLayoutPending(ASHierarchyState hierarchyStat
|
|||||||
return ((hierarchyState & ASHierarchyStateLayoutPending) == ASHierarchyStateLayoutPending);
|
return ((hierarchyState & ASHierarchyStateLayoutPending) == ASHierarchyStateLayoutPending);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline BOOL ASHierarchyStateIncludesRangeManaged(ASHierarchyState hierarchyState)
|
||||||
|
{
|
||||||
|
return ((hierarchyState & ASHierarchyStateRangeManaged) == ASHierarchyStateRangeManaged);
|
||||||
|
}
|
||||||
|
|
||||||
@interface ASDisplayNode ()
|
@interface ASDisplayNode ()
|
||||||
{
|
{
|
||||||
@protected
|
@protected
|
||||||
@ -91,6 +96,14 @@ inline BOOL ASHierarchyStateIncludesLayoutPending(ASHierarchyState hierarchyStat
|
|||||||
*/
|
*/
|
||||||
@property (nonatomic, readwrite) ASHierarchyState hierarchyState;
|
@property (nonatomic, readwrite) ASHierarchyState hierarchyState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Return if the node is range managed or not
|
||||||
|
*
|
||||||
|
* @discussion Currently only set interface state on nodes in table and collection views. For other nodes, if they are
|
||||||
|
* in the hierarchy we enable all ASInterfaceState types with `ASInterfaceStateInHierarchy`, otherwise `None`.
|
||||||
|
*/
|
||||||
|
- (BOOL)supportsRangeManagedInterfaceState;
|
||||||
|
|
||||||
// The two methods below will eventually be exposed, but their names are subject to change.
|
// The two methods below will eventually be exposed, but their names are subject to change.
|
||||||
/**
|
/**
|
||||||
* @abstract Ensure that all rendering is complete for this node and its descendents.
|
* @abstract Ensure that all rendering is complete for this node and its descendents.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user