1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-02 17:38:07 +01:00
Telegram/Telegraph/TGTextMessageBackgroundViewModel.m

196 lines
7.2 KiB
Mathematica
Raw Normal View History

2014-07-10 16:11:09 +02:00
#import "TGTextMessageBackgroundViewModel.h"
#define TGTextMessageBackgroundImageDef(name, incoming, filePhone, filePad) \
static UIImage *name() \
{ \
static UIImage *image = nil; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^ \
{ \
image = [[UIImage imageNamed:[[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone ? filePhone : filePad] stretchableImageWithLeftCapWidth:incoming ? 23 : (40 - 23) topCapHeight:16]; \
}); \
return image; \
}
TGTextMessageBackgroundImageDef(incomingImage, true, @"ModernBubbleIncomingFull.png", @"ModernBubbleIncomingFullPad.png")
TGTextMessageBackgroundImageDef(incomingImageHighlighted, true, @"ModernBubbleIncomingFullHighlighted.png", @"ModernBubbleIncomingFullHighlightedPad.png")
TGTextMessageBackgroundImageDef(incomingPartialImage, true, @"ModernBubbleIncomingPartial.png", @"ModernBubbleIncomingPartialPad.png")
TGTextMessageBackgroundImageDef(incomingPartialImageHighlighted, true, @"ModernBubbleIncomingPartialHighlighted.png", @"ModernBubbleIncomingPartialHighlightedPad.png")
TGTextMessageBackgroundImageDef(outgoingImage, false, @"ModernBubbleOutgoingFull.png", @"ModernBubbleOutgoingFullPad.png")
TGTextMessageBackgroundImageDef(outgoingImageHighlighted, false, @"ModernBubbleOutgoingFullHighlighted.png", @"ModernBubbleOutgoingFullHighlightedPad.png")
TGTextMessageBackgroundImageDef(outgoingPartialImage, false, @"ModernBubbleOutgoingPartial.png", @"ModernBubbleOutgoingPartialPad.png")
TGTextMessageBackgroundImageDef(outgoingPartialImageHighlighted, false, @"ModernBubbleOutgoingPartialHighlighted.png", @"ModernBubbleOutgoingPartialHighlightedPad.png")
@interface TGTextMessageBackgroundViewModel ()
{
TGTextMessageBackgroundType _type;
bool _imageIsValid;
bool _highlighted;
}
@end
@implementation TGTextMessageBackgroundViewModel
- (instancetype)initWithType:(TGTextMessageBackgroundType)type
{
self = [super initWithImage:nil];
if (self != nil)
{
_type = type;
}
return self;
}
- (void)bindViewToContainer:(UIView *)container viewStorage:(TGModernViewStorage *)viewStorage
{
_highlighted = false;
if (!_imageIsValid)
{
_imageIsValid = true;
self.image = _type == TGTextMessageBackgroundIncoming ? (_partialMode ? incomingPartialImage() : incomingImage()) : (_partialMode ? outgoingPartialImage() : outgoingImage());
}
[super bindViewToContainer:container viewStorage:viewStorage];
}
- (void)setPartialMode:(bool)partialMode
{
if (_partialMode != partialMode)
{
bool wasPartial = _partialMode;
_partialMode = partialMode;
_imageIsValid = false;
if ([self boundView] != nil)
{
UIImageView *boundView = (UIImageView *)[self boundView];
_imageIsValid = !_highlighted;
UIImage *previousImage = self.image;
UIImage *newImage = [self currentImage];
self.image = newImage;
if (previousImage != nil && iosMajorVersion() >= 7)
{
UIImageView *overlayImageView = [[UIImageView alloc] initWithFrame:boundView.bounds];
if (!wasPartial)
{
boundView.image = newImage;
overlayImageView.image = previousImage;
}
else
{
boundView.image = previousImage;
overlayImageView.image = newImage;
overlayImageView.alpha = 0.0f;
}
[boundView addSubview:overlayImageView];
[UIView animateWithDuration:0.3 * 0.7 animations:^
{
overlayImageView.alpha = wasPartial ? 1.0f : 0.0f;
} completion:^(__unused BOOL finished)
{
if (finished && wasPartial)
boundView.image = newImage;
[overlayImageView removeFromSuperview];
}];
}
else
[(UIImageView *)[self boundView] setImage:self.image];
}
}
}
- (UIImage *)currentImage
{
UIImage *newImage = nil;
if (_type == TGTextMessageBackgroundIncoming)
{
if (_partialMode)
newImage = _highlighted ? incomingPartialImageHighlighted() : incomingPartialImage();
else
newImage = _highlighted ? incomingImageHighlighted() : incomingImage();
}
else
{
if (_partialMode)
newImage = _highlighted ? outgoingPartialImageHighlighted() : outgoingPartialImage();
else
newImage = _highlighted ? outgoingImageHighlighted() : outgoingImage();
}
return newImage;
}
- (void)setHighlightedIfBound
{
if ([self boundView] != nil && !_highlighted)
{
_highlighted = true;
_imageIsValid = false;
self.image = [self currentImage];
((UIImageView *)[self boundView]).image = self.image;
}
}
- (void)addScaleAnimationToLayer:(CALayer *)layer from:(CGSize)fromScale to:(CGSize)toScale duration:(NSTimeInterval)duration
{;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(fromScale.width, fromScale.height, 1.0f)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(toScale.width, toScale.height, 1.0f)];
animation.duration = duration;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.removedOnCompletion = true;
animation.fillMode = kCAFillModeForwards;
[layer addAnimation:animation forKey:@"transform"];
}
- (void)clearHighlight
{
if (_highlighted)
{
_highlighted = false;
if ([self boundView] != nil)
{
UIImage *previousImage = self.image;
UIImage *newImage = [self currentImage];
self.image = newImage;
_imageIsValid = true;
((UIImageView *)[self boundView]).image = self.image;
if (previousImage != nil && iosMajorVersion() >= 7)
{
UIImageView *overlayImageView = [[UIImageView alloc] initWithFrame:[self boundView].frame];
overlayImageView.image = previousImage;
[[self boundView].superview insertSubview:overlayImageView aboveSubview:[self boundView]];
CGSize frameSize = [self boundView].frame.size;
[self addScaleAnimationToLayer:[self boundView].layer from:CGSizeMake((frameSize.width - 2.0f) / frameSize.width, (frameSize.height - 2.0f) / frameSize.height) to:CGSizeMake(1.0f, 1.0f) duration:0.2];
[UIView animateWithDuration:0.4 animations:^
{
overlayImageView.alpha = 0.0f;
} completion:^(__unused BOOL finished)
{
[overlayImageView removeFromSuperview];
}];
}
}
}
}
@end