mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
Build ChatListUI
This commit is contained in:
@@ -0,0 +1,359 @@
|
||||
/**
|
||||
Copyright (c) 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the BSD-style license found in the
|
||||
LICENSE file in the root directory of this source tree. An additional grant
|
||||
of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "POPAnimationInternal.h"
|
||||
#import "POPPropertyAnimation.h"
|
||||
|
||||
static void clampValue(CGFloat &value, CGFloat fromValue, CGFloat toValue, NSUInteger clamp)
|
||||
{
|
||||
BOOL increasing = (toValue > fromValue);
|
||||
|
||||
// Clamp start of animation.
|
||||
if ((kPOPAnimationClampStart & clamp) &&
|
||||
((increasing && (value < fromValue)) || (!increasing && (value > fromValue)))) {
|
||||
value = fromValue;
|
||||
}
|
||||
|
||||
// Clamp end of animation.
|
||||
if ((kPOPAnimationClampEnd & clamp) &&
|
||||
((increasing && (value > toValue)) || (!increasing && (value < toValue)))) {
|
||||
value = toValue;
|
||||
}
|
||||
}
|
||||
|
||||
struct _POPPropertyAnimationState : _POPAnimationState
|
||||
{
|
||||
POPAnimatableProperty *property;
|
||||
POPValueType valueType;
|
||||
NSUInteger valueCount;
|
||||
VectorRef fromVec;
|
||||
VectorRef toVec;
|
||||
VectorRef currentVec;
|
||||
VectorRef previousVec;
|
||||
VectorRef previous2Vec;
|
||||
VectorRef velocityVec;
|
||||
VectorRef originalVelocityVec;
|
||||
VectorRef distanceVec;
|
||||
CGFloat roundingFactor;
|
||||
NSUInteger clampMode;
|
||||
NSArray *progressMarkers;
|
||||
POPProgressMarker *progressMarkerState;
|
||||
NSUInteger progressMarkerCount;
|
||||
NSUInteger nextProgressMarkerIdx;
|
||||
CGFloat dynamicsThreshold;
|
||||
|
||||
_POPPropertyAnimationState(id __unsafe_unretained anim) : _POPAnimationState(anim),
|
||||
property(nil),
|
||||
valueType((POPValueType)0),
|
||||
valueCount(0),
|
||||
fromVec(nullptr),
|
||||
toVec(nullptr),
|
||||
currentVec(nullptr),
|
||||
previousVec(nullptr),
|
||||
previous2Vec(nullptr),
|
||||
velocityVec(nullptr),
|
||||
originalVelocityVec(nullptr),
|
||||
distanceVec(nullptr),
|
||||
roundingFactor(0),
|
||||
clampMode(0),
|
||||
progressMarkers(nil),
|
||||
progressMarkerState(nil),
|
||||
progressMarkerCount(0),
|
||||
nextProgressMarkerIdx(0),
|
||||
dynamicsThreshold(0)
|
||||
{
|
||||
type = kPOPAnimationBasic;
|
||||
}
|
||||
|
||||
~_POPPropertyAnimationState()
|
||||
{
|
||||
if (progressMarkerState) {
|
||||
free(progressMarkerState);
|
||||
progressMarkerState = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool canProgress() {
|
||||
return hasValue();
|
||||
}
|
||||
|
||||
bool shouldRound() {
|
||||
return 0 != roundingFactor;
|
||||
}
|
||||
|
||||
bool hasValue() {
|
||||
return 0 != valueCount;
|
||||
}
|
||||
|
||||
bool isDone() {
|
||||
// inherit done
|
||||
if (_POPAnimationState::isDone()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// consider an animation with no values done
|
||||
if (!hasValue() && !isCustom()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// returns a copy of the currentVec, rounding if needed
|
||||
VectorRef currentValue() {
|
||||
VectorRef vec = VectorRef(Vector::new_vector(currentVec.get()));
|
||||
if (shouldRound()) {
|
||||
vec->subRound(1 / roundingFactor);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
void resetProgressMarkerState()
|
||||
{
|
||||
for (NSUInteger idx = 0; idx < progressMarkerCount; idx++)
|
||||
progressMarkerState[idx].reached = false;
|
||||
|
||||
nextProgressMarkerIdx = 0;
|
||||
}
|
||||
|
||||
void updatedProgressMarkers()
|
||||
{
|
||||
if (progressMarkerState) {
|
||||
free(progressMarkerState);
|
||||
progressMarkerState = NULL;
|
||||
}
|
||||
|
||||
progressMarkerCount = progressMarkers.count;
|
||||
|
||||
if (0 != progressMarkerCount) {
|
||||
progressMarkerState = (POPProgressMarker *)malloc(progressMarkerCount * sizeof(POPProgressMarker));
|
||||
[progressMarkers enumerateObjectsUsingBlock:^(NSNumber *progressMarker, NSUInteger idx, BOOL *stop) {
|
||||
progressMarkerState[idx].reached = false;
|
||||
progressMarkerState[idx].progress = [progressMarker floatValue];
|
||||
}];
|
||||
}
|
||||
|
||||
nextProgressMarkerIdx = 0;
|
||||
}
|
||||
|
||||
virtual void updatedDynamicsThreshold()
|
||||
{
|
||||
dynamicsThreshold = property.threshold;
|
||||
}
|
||||
|
||||
void finalizeProgress()
|
||||
{
|
||||
progress = 1.0;
|
||||
NSUInteger count = valueCount;
|
||||
VectorRef outVec(Vector::new_vector(count, NULL));
|
||||
|
||||
if (outVec && toVec) {
|
||||
*outVec = *toVec;
|
||||
}
|
||||
|
||||
currentVec = outVec;
|
||||
clampCurrentValue();
|
||||
delegateProgress();
|
||||
}
|
||||
|
||||
void computeProgress() {
|
||||
if (!canProgress()) {
|
||||
return;
|
||||
}
|
||||
|
||||
static ComputeProgressFunctor<Vector4r> func;
|
||||
Vector4r v = vector4(currentVec);
|
||||
Vector4r f = vector4(fromVec);
|
||||
Vector4r t = vector4(toVec);
|
||||
progress = func(v, f, t);
|
||||
}
|
||||
|
||||
void delegateProgress() {
|
||||
if (!canProgress()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegateDidProgress && progressMarkerState) {
|
||||
|
||||
while (nextProgressMarkerIdx < progressMarkerCount) {
|
||||
if (progress < progressMarkerState[nextProgressMarkerIdx].progress)
|
||||
break;
|
||||
|
||||
if (!progressMarkerState[nextProgressMarkerIdx].reached) {
|
||||
ActionEnabler enabler;
|
||||
[delegate pop_animation:self didReachProgress:progressMarkerState[nextProgressMarkerIdx].progress];
|
||||
progressMarkerState[nextProgressMarkerIdx].reached = true;
|
||||
}
|
||||
|
||||
nextProgressMarkerIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!didReachToValue) {
|
||||
bool didReachToValue = false;
|
||||
if (0 == valueCount) {
|
||||
didReachToValue = true;
|
||||
} else {
|
||||
Vector4r distance = toVec->vector4r();
|
||||
distance -= currentVec->vector4r();
|
||||
|
||||
if (0 == distance.squaredNorm()) {
|
||||
didReachToValue = true;
|
||||
} else {
|
||||
// components
|
||||
if (distanceVec) {
|
||||
didReachToValue = true;
|
||||
const CGFloat *distanceValues = distanceVec->data();
|
||||
for (NSUInteger idx = 0; idx < valueCount; idx++) {
|
||||
didReachToValue &= (signbit(distance[idx]) != signbit(distanceValues[idx]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (didReachToValue) {
|
||||
handleDidReachToValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleDidReachToValue() {
|
||||
didReachToValue = true;
|
||||
|
||||
if (delegateDidReachToValue) {
|
||||
ActionEnabler enabler;
|
||||
[delegate pop_animationDidReachToValue:self];
|
||||
}
|
||||
|
||||
POPAnimationDidReachToValueBlock block = animationDidReachToValueBlock;
|
||||
if (block != NULL) {
|
||||
ActionEnabler enabler;
|
||||
block(self);
|
||||
}
|
||||
|
||||
if (tracing) {
|
||||
[tracer didReachToValue:POPBox(currentValue(), valueType, true)];
|
||||
}
|
||||
}
|
||||
|
||||
void readObjectValue(VectorRef *ptrVec, id obj)
|
||||
{
|
||||
// use current object value as from value
|
||||
pop_animatable_read_block read = property.readBlock;
|
||||
if (NULL != read) {
|
||||
|
||||
Vector4r vec = read_values(read, obj, valueCount);
|
||||
*ptrVec = VectorRef(Vector::new_vector(valueCount, vec));
|
||||
|
||||
if (tracing) {
|
||||
[tracer readPropertyValue:POPBox(*ptrVec, valueType, true)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void willRun(bool started, id obj) {
|
||||
// ensure from value initialized
|
||||
if (NULL == fromVec) {
|
||||
readObjectValue(&fromVec, obj);
|
||||
}
|
||||
|
||||
// ensure to value initialized
|
||||
if (NULL == toVec) {
|
||||
// compute decay to value
|
||||
if (kPOPAnimationDecay == type) {
|
||||
[self toValue];
|
||||
} else {
|
||||
// read to value
|
||||
readObjectValue(&toVec, obj);
|
||||
}
|
||||
}
|
||||
|
||||
// handle one time value initialization on start
|
||||
if (started) {
|
||||
|
||||
// initialize current vec
|
||||
if (!currentVec) {
|
||||
currentVec = VectorRef(Vector::new_vector(valueCount, NULL));
|
||||
|
||||
// initialize current value with from value
|
||||
// only do this on initial creation to avoid overwriting current value
|
||||
// on paused animation continuation
|
||||
if (currentVec && fromVec) {
|
||||
*currentVec = *fromVec;
|
||||
}
|
||||
}
|
||||
|
||||
// ensure velocity values
|
||||
if (!velocityVec) {
|
||||
velocityVec = VectorRef(Vector::new_vector(valueCount, NULL));
|
||||
}
|
||||
if (!originalVelocityVec) {
|
||||
originalVelocityVec = VectorRef(Vector::new_vector(valueCount, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
// ensure distance value initialized
|
||||
// depends on current value set on one time start
|
||||
if (NULL == distanceVec) {
|
||||
|
||||
// not yet started animations may not have current value
|
||||
VectorRef fromVec2 = NULL != currentVec ? currentVec : fromVec;
|
||||
|
||||
if (fromVec2 && toVec) {
|
||||
Vector4r distance = toVec->vector4r();
|
||||
distance -= fromVec2->vector4r();
|
||||
|
||||
if (0 != distance.squaredNorm()) {
|
||||
distanceVec = VectorRef(Vector::new_vector(valueCount, distance));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void reset(bool all) {
|
||||
_POPAnimationState::reset(all);
|
||||
|
||||
if (all) {
|
||||
currentVec = NULL;
|
||||
previousVec = NULL;
|
||||
previous2Vec = NULL;
|
||||
}
|
||||
progress = 0;
|
||||
resetProgressMarkerState();
|
||||
didReachToValue = false;
|
||||
distanceVec = NULL;
|
||||
}
|
||||
|
||||
void clampCurrentValue(NSUInteger clamp)
|
||||
{
|
||||
if (kPOPAnimationClampNone == clamp)
|
||||
return;
|
||||
|
||||
// Clamp all vector values
|
||||
CGFloat *currentValues = currentVec->data();
|
||||
const CGFloat *fromValues = fromVec->data();
|
||||
const CGFloat *toValues = toVec->data();
|
||||
|
||||
for (NSUInteger idx = 0; idx < valueCount; idx++) {
|
||||
clampValue(currentValues[idx], fromValues[idx], toValues[idx], clamp);
|
||||
}
|
||||
}
|
||||
|
||||
void clampCurrentValue()
|
||||
{
|
||||
clampCurrentValue(clampMode);
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct _POPPropertyAnimationState POPPropertyAnimationState;
|
||||
|
||||
@interface POPPropertyAnimation ()
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user