no message

This commit is contained in:
Ilya Laktyushin
2017-10-05 23:50:33 +03:00
parent ff88cb94b7
commit b28e18e44f
9 changed files with 245 additions and 87 deletions

View File

@@ -22,6 +22,7 @@
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, assign) int32_t messageId;
@property (nonatomic, assign) bool isOwn;
@property (nonatomic, assign) bool hasSession;
@property (nonatomic, assign) bool isExpired;
- (instancetype)initWithLocation:(TGLocationMediaAttachment *)location;

View File

@@ -76,6 +76,16 @@
}
}
- (void)setHasSession:(bool)hasSession
{
if (hasSession != _hasSession)
{
[self willChangeValueForKey:@"hasSession"];
_hasSession = hasSession;
[self didChangeValueForKey:@"hasSession"];
}
}
- (bool)isLiveLocation
{
return _location.period > 0;

View File

@@ -6,6 +6,8 @@
@interface TGLocationLiveCell : UITableViewCell
@property (nonatomic, copy) void (^longPressed)(void);
@property (nonatomic, readonly) int32_t messageId;
@property (nonatomic, weak) UIImageView *edgeView;

View File

@@ -37,6 +37,8 @@ const CGFloat TGLocationLiveCellHeight = 68;
SMetaDisposable *_locationDisposable;
SMetaDisposable *_remainingDisposable;
UILongPressGestureRecognizer *_longPressGestureRecognizer;
}
@end
@@ -92,6 +94,9 @@ const CGFloat TGLocationLiveCellHeight = 68;
_wavesView = [[TGLocationWavesView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 48.0f, 48.0f)];
[_circleView addSubview:_wavesView];
_longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlePress:)];
[self addGestureRecognizer:_longPressGestureRecognizer];
}
return self;
}
@@ -102,6 +107,15 @@ const CGFloat TGLocationLiveCellHeight = 68;
[_wavesView invalidate];
}
- (void)handlePress:(UILongPressGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
{
if (self.longPressed != nil)
self.longPressed();
}
}
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
if (animated)

View File

@@ -48,6 +48,7 @@
@property (nonatomic, strong) id receivingPeer;
- (void)_presentLiveLocationMenu:(CLLocationCoordinate2D)coordinate dismissOnCompletion:(bool)dismissOnCompletion;
- (CGRect)_liveLocationMenuSourceRect;
- (void)_willStartOwnLiveLocation;
@end

View File

@@ -357,19 +357,6 @@ const CGFloat TGLocationMapInset = 100.0f;
return [_userLocation signal];
}
- (void)dismissLiveLocationMenu:(TGMenuSheetController *)controller doNotRemove:(bool)doNotRemove
{
if (!doNotRemove)
{
[controller dismissAnimated:true];
}
else
{
[controller setDimViewHidden:true animated:true];
[controller removeFromParentViewController];
}
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
if (_openLiveLocationMenuBlock != nil)
@@ -386,6 +373,26 @@ const CGFloat TGLocationMapInset = 100.0f;
return CGRectZero;
}
- (void)_willStartOwnLiveLocation
{
}
- (void)dismissLiveLocationMenu:(TGMenuSheetController *)controller doNotRemove:(bool)doNotRemove
{
[self _willStartOwnLiveLocation];
if (!doNotRemove)
{
[controller dismissAnimated:true];
}
else
{
[controller setDimViewHidden:true animated:true];
[controller removeFromParentViewController];
}
}
- (void)_presentLiveLocationMenu:(CLLocationCoordinate2D)coordinate dismissOnCompletion:(bool)dismissOnCompletion
{
void (^block)(void) = ^

View File

@@ -119,44 +119,50 @@ NSString *const TGLocationPinAnnotationKind = @"TGLocationPinAnnotation";
if (animated)
{
[self layoutSubviews];
_animating = true;
if (selected)
{
UIView *avatarSnapshot = [_avatarView snapshotViewAfterScreenUpdates:false];
[_smallView addSubview:avatarSnapshot];
avatarSnapshot.transform = _avatarView.transform;
avatarSnapshot.center = CGPointMake(_smallView.frame.size.width / 2.0f, _smallView.frame.size.height / 2.0f);
_avatarView.transform = CGAffineTransformIdentity;
[_backgroundView addSubview:_avatarView];
_avatarView.center = CGPointMake(_backgroundView.frame.size.width / 2.0f, _backgroundView.frame.size.height / 2.0f - 5.0f);
_dotView.alpha = 0.0f;
_shadowView.center = CGPointMake(_shadowView.center.x, _shadowView.center.y + _shadowView.frame.size.height / 2.0f);
_shadowView.layer.anchorPoint = CGPointMake(0.5f, 1.0f);
_shadowView.hidden = false;
_shadowView.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
[UIView animateWithDuration:0.35 delay:0.0 usingSpringWithDamping:0.6f initialSpringVelocity:0.5f options:kNilOptions animations:^
{
_smallView.transform = CGAffineTransformMakeScale(0.001f, 0.001f);
_shadowView.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished)
{
_animating = false;
_shadowView.layer.anchorPoint = CGPointMake(0.5f, 0.5f);
//dispatch_async(dispatch_get_main_queue(), ^
//{
UIView *avatarSnapshot = [_avatarView snapshotViewAfterScreenUpdates:false];
[_smallView addSubview:avatarSnapshot];
avatarSnapshot.transform = _avatarView.transform;
avatarSnapshot.center = CGPointMake(_smallView.frame.size.width / 2.0f, _smallView.frame.size.height / 2.0f);
_smallView.hidden = true;
_smallView.transform = CGAffineTransformIdentity;
[avatarSnapshot removeFromSuperview];
_avatarView.transform = CGAffineTransformIdentity;
[_backgroundView addSubview:_avatarView];
_avatarView.center = CGPointMake(_backgroundView.frame.size.width / 2.0f, _backgroundView.frame.size.height / 2.0f - 5.0f);
[self addSubview:_avatarView];
}];
[UIView animateWithDuration:0.2 animations:^
{
_dotView.alpha = 1.0f;
}];
_dotView.alpha = 0.0f;
_shadowView.center = CGPointMake(_shadowView.center.x, _shadowView.center.y + _shadowView.frame.size.height / 2.0f);
_shadowView.layer.anchorPoint = CGPointMake(0.5f, 1.0f);
_shadowView.hidden = false;
_shadowView.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
[UIView animateWithDuration:0.35 delay:0.0 usingSpringWithDamping:0.6f initialSpringVelocity:0.5f options:kNilOptions animations:^
{
_smallView.transform = CGAffineTransformMakeScale(0.001f, 0.001f);
_shadowView.transform = CGAffineTransformIdentity;
if (_dotView.hidden)
_smallView.alpha = 0.0f;
} completion:^(BOOL finished)
{
_animating = false;
_shadowView.layer.anchorPoint = CGPointMake(0.5f, 0.5f);
_smallView.hidden = true;
_smallView.transform = CGAffineTransformIdentity;
[avatarSnapshot removeFromSuperview];
[self addSubview:_avatarView];
}];
[UIView animateWithDuration:0.2 animations:^
{
_dotView.alpha = 1.0f;
}];
//});
}
else
{
@@ -178,6 +184,8 @@ NSString *const TGLocationPinAnnotationKind = @"TGLocationPinAnnotation";
{
_smallView.transform = CGAffineTransformIdentity;
_shadowView.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
if (_dotView.hidden)
_smallView.alpha = 1.0f;
} completion:^(BOOL finished)
{
_animating = false;
@@ -201,6 +209,7 @@ NSString *const TGLocationPinAnnotationKind = @"TGLocationPinAnnotation";
_smallView.hidden = selected;
_shadowView.hidden = !selected;
_dotView.alpha = selected ? 1.0f : 0.0f;
_smallView.alpha = 1.0f;
[self layoutSubviews];
}
}
@@ -225,12 +234,11 @@ NSString *const TGLocationPinAnnotationKind = @"TGLocationPinAnnotation";
}
else if ([annotation isKindOfClass:[TGLocationAnnotation class]])
{
_dotView.hidden = false;
TGLocationAnnotation *locationAnnotation = ((TGLocationAnnotation *)annotation);
TGLocationMediaAttachment *location = locationAnnotation.location;
if (location.period == 0)
{
_dotView.hidden = false;
_avatarView.hidden = true;
_avatarView.alpha = 1.0f;
_iconView.hidden = false;
@@ -259,17 +267,19 @@ NSString *const TGLocationPinAnnotationKind = @"TGLocationPinAnnotation";
_backgroundView.image = TGComponentsImageNamed(@"LocationPinBackground");
[self setPeer:locationAnnotation.peer];
if (!locationAnnotation.isOwn && !locationAnnotation.isExpired)
if (!locationAnnotation.isOwn)
{
[_pulseView start];
[self subscribeForExpiration];
if (!locationAnnotation.isExpired)
[_pulseView start];
_dotView.hidden = false;
}
else
{
[self unsubscribeFromExpiration];
_dotView.hidden = true;
}
[self subscribeForExpiration];
_liveLocation = true;
if (!self.selected)

View File

@@ -13,10 +13,11 @@
@property (nonatomic, strong, readonly) TGMessage *message;
@property (nonatomic, strong, readonly) id peer;
@property (nonatomic, readonly) bool isOwn;
@property (nonatomic, readonly) bool hasOwnSession;
@property (nonatomic, readonly) bool isOwnLocation;
@property (nonatomic, readonly) bool isExpired;
- (instancetype)initWithMessage:(TGMessage *)message peer:(id)peer isOwn:(bool)isOwn isExpired:(bool)isExpired;
- (instancetype)initWithMessage:(TGMessage *)message peer:(id)peer hasOwnSession:(bool)hasOwnSession isOwnLocation:(bool)isOwnLocation isExpired:(bool)isExpired;
- (instancetype)initWithMessage:(TGMessage *)message peer:(id)peer;
- (int64_t)peerId;
@@ -34,7 +35,9 @@
@property (nonatomic, copy) bool (^presentShareMenu)(TGMenuSheetController *, CLLocationCoordinate2D);
@property (nonatomic, copy) bool (^presentOpenInMenu)(TGLocationViewController *, TGLocationMediaAttachment *, bool, void (^)(TGMenuSheetController *));
@property (nonatomic, copy) void (^shareAction)(NSArray *peerIds, NSString *caption);
@property (nonatomic, copy) void (^calloutPressed)(void);
@property (nonatomic, copy) void (^openLocation)(TGMessage *message);
@property (nonatomic, copy) void (^onViewDidAppear)(void);
@property (nonatomic, readonly) UIButton *directionsButton;

View File

@@ -38,6 +38,7 @@
@interface TGLocationViewController () <MKMapViewDelegate>
{
id<LegacyComponentsContext> _context;
bool _dismissing;
id _peer;
TGMessage *_message;
@@ -64,6 +65,7 @@
bool _presentedLiveLocations;
bool _selectedCurrentLiveLocation;
bool _ignoreNextUpdates;
bool _focusOnOwnLocation;
TGLocationPinAnnotationView *_ownLiveLocationView;
__weak MKAnnotationView *_userLocationView;
@@ -107,7 +109,7 @@
if (liveLocation)
{
_liveLocations = @[liveLocation];
_hasOwnLiveLocation = liveLocation.isOwn;
_hasOwnLiveLocation = liveLocation.hasOwnSession;
if (_hasOwnLiveLocation)
_ownLocationExpired = liveLocation.isExpired;
}
@@ -165,7 +167,27 @@
- (void)setLiveLocationsSignal:(SSignal *)signal
{
_signal = signal;
if (_currentLiveLocation.isOwnLocation)
{
_signal = [[signal reduceLeftWithPassthrough:nil with:^id(id current, id value, void (^emit)(id))
{
if (current == nil)
{
emit([SSignal single:value]);
return @true;
}
else
{
emit([[SSignal single:value] delay:0.25 onQueue:[SQueue concurrentDefaultQueue]]);
return current;
}
}] switchToLatest];
}
else
{
_signal = signal;
}
[self setupSignals];
}
@@ -177,7 +199,7 @@
TGLiveLocation *ownLiveLocation = nil;
for (TGLiveLocation *liveLocation in liveLocations)
{
if (liveLocation.isOwn)
if (liveLocation.hasOwnSession)
{
ownLiveLocation = liveLocation;
break;
@@ -199,7 +221,7 @@
_ownLiveLocationView.frame = CGRectOffset(_ownLiveLocationView.frame, 21.0f, 22.0f);
[_userLocationView addSubview:_ownLiveLocationView];
if (_currentLiveLocation.isOwn)
if (_currentLiveLocation.hasOwnSession)
[self selectOwnAnnotationAnimated:false];
}
else
@@ -233,7 +255,7 @@
}
}
if (_currentLiveLocation.isOwn && !_ownLocationExpired && !self.zoomToFitAllLocationsOnScreen)
if (_currentLiveLocation.hasOwnSession && !_ownLocationExpired && !self.zoomToFitAllLocationsOnScreen)
{
[_mapView setUserTrackingMode:[TGLocationTrackingButton userTrackingModeWithLocationTrackingMode:TGLocationTrackingModeFollow] animated:false];
[_optionsView setTrackingMode:TGLocationTrackingModeFollow animated:true];
@@ -324,7 +346,7 @@
NSMutableDictionary *liveLocations = [[NSMutableDictionary alloc] init];
for (TGLiveLocation *liveLocation in _liveLocations)
{
if (!liveLocation.isOwn || liveLocation.isExpired)
if (!liveLocation.hasOwnSession || liveLocation.isExpired)
liveLocations[@(liveLocation.message.mid)] = liveLocation;
}
@@ -479,6 +501,13 @@
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (self.onViewDidAppear != nil)
self.onViewDidAppear();
}
- (void)setupSignals
{
SSignal *combinedSignal = [SSignal combineSignals:@[ [[[self userLocationSignal] deliverOn:[SQueue concurrentBackgroundQueue]] map:^id(id location) {
@@ -495,12 +524,16 @@
if (strongSelf == nil)
return;
if (strongSelf->_dismissing)
return;
CLLocation *currentLocation = [next.firstObject isKindOfClass:[CLLocation class]] ? next.firstObject : nil;
NSArray *liveLocations = next.lastObject;
bool actual = liveLocations.count > 0;
NSMutableArray *filteredLiveLocations = [[NSMutableArray alloc] init];
bool hasCurrentLocation = false;
bool currentExpiredLocationIsOwn = false;
for (TGLiveLocation *liveLocation in liveLocations)
{
if (!liveLocation.isExpired)
@@ -512,19 +545,39 @@
{
bool isChannel = [strongSelf->_currentLiveLocation.peer isKindOfClass:[TGConversation class]] && !((TGConversation *)strongSelf->_currentLiveLocation.peer).isChannelGroup;
TGLiveLocation *currentExpiredLiveLocation = [[TGLiveLocation alloc] initWithMessage:strongSelf->_currentLiveLocation.message peer:strongSelf->_currentLiveLocation.peer isOwn:strongSelf->_currentLiveLocation.isOwn isExpired:isChannel ? strongSelf->_currentLiveLocation.isExpired : true];
TGLiveLocation *currentExpiredLiveLocation = [[TGLiveLocation alloc] initWithMessage:strongSelf->_currentLiveLocation.message peer:strongSelf->_currentLiveLocation.peer hasOwnSession:strongSelf->_currentLiveLocation.hasOwnSession isOwnLocation:strongSelf->_currentLiveLocation.isOwnLocation isExpired:isChannel ? strongSelf->_currentLiveLocation.isExpired : true];
[filteredLiveLocations addObject:currentExpiredLiveLocation];
if (currentExpiredLiveLocation.isOwnLocation && currentExpiredLiveLocation.isExpired)
currentExpiredLocationIsOwn = true;
}
liveLocations = filteredLiveLocations;
for (TGLiveLocation *location in filteredLiveLocations)
{
if (strongSelf->_ignoreNextUpdates && location.hasOwnSession && !location.isExpired && (currentExpiredLocationIsOwn || (strongSelf->_currentLiveLocation.isOwnLocation && strongSelf->_currentLiveLocation.isExpired)))
{
strongSelf->_dismissing = true;
TGDispatchOnMainThread(^
{
if (strongSelf.openLocation != nil)
strongSelf.openLocation(location.message);
});
return;
}
}
if (strongSelf->_ignoreNextUpdates)
return;
NSMutableArray *sortedLiveLocations = [liveLocations mutableCopy];
if (currentLocation != nil)
{
[sortedLiveLocations sortUsingComparator:^NSComparisonResult(TGLiveLocation *obj1, TGLiveLocation *obj2)
{
if (obj1.isOwn)
if (obj1.hasOwnSession)
return NSOrderedAscending;
else if (obj2.isOwn)
else if (obj2.hasOwnSession)
return NSOrderedDescending;
if (obj1.message.mid == strongSelf->_currentLiveLocation.message.mid)
@@ -547,9 +600,9 @@
{
[sortedLiveLocations sortUsingComparator:^NSComparisonResult(TGLiveLocation *obj1, TGLiveLocation *obj2)
{
if (obj1.isOwn)
if (obj1.hasOwnSession)
return NSOrderedAscending;
else if (obj2.isOwn)
else if (obj2.hasOwnSession)
return NSOrderedDescending;
if (obj1.message.mid == strongSelf->_currentLiveLocation.message.mid)
@@ -751,26 +804,64 @@
[_ownLiveLocationView.superview.superview bringSubviewToFront:_ownLiveLocationView.superview];
}
- (void)getDirectionsPressed
- (void)getDirectionsPressed:(TGLocationMediaAttachment *)locationAttachment prompt:(bool)prompt
{
TGLocationMediaAttachment *locationAttachment = _locationAttachment;
if (locationAttachment == nil)
return;
if (_presentOpenInMenu && _presentOpenInMenu(self, locationAttachment, true, nil))
{
}
else
{
NSString *title = @"";
if (locationAttachment.venue != nil)
title = locationAttachment.venue.title;
else if ([_peer isKindOfClass:[TGUser class]])
title = ((TGUser *)_peer).displayName;
else if ([_peer isKindOfClass:[TGConversation class]])
title = ((TGConversation *)_peer).chatTitle;
void (^block)(void) = ^
{
NSString *title = @"";
if (locationAttachment.venue != nil)
title = locationAttachment.venue.title;
else if ([_peer isKindOfClass:[TGUser class]])
title = ((TGUser *)_peer).displayName;
else if ([_peer isKindOfClass:[TGConversation class]])
title = ((TGConversation *)_peer).chatTitle;
[TGLocationUtils openMapsWithCoordinate:[self locationCoordinate] withDirections:true locationName:title];
};
[TGLocationUtils openMapsWithCoordinate:[self locationCoordinate] withDirections:true locationName:title];
if (prompt)
{
TGMenuSheetController *controller = [[TGMenuSheetController alloc] initWithContext:_context dark:false];
controller.dismissesByOutsideTap = true;
controller.narrowInLandscape = true;
__weak TGMenuSheetController *weakController = controller;
NSArray *items = @
[
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.GetDirections") type:TGMenuSheetButtonTypeDefault action:^
{
__strong TGMenuSheetController *strongController = weakController;
if (strongController == nil)
return;
[strongController dismissAnimated:true];
block();
}],
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
{
__strong TGMenuSheetController *strongController = weakController;
if (strongController != nil)
[strongController dismissAnimated:true];
}]
];
[controller setItemViews:items];
controller.sourceRect = ^
{
return CGRectZero;
};
controller.permittedArrowDirections = UIPopoverArrowDirectionUp;
[controller presentInViewController:self sourceView:self.view animated:true];
}
else
{
block();
}
}
}
@@ -822,7 +913,7 @@
{
[_userLocationView addSubview:_ownLiveLocationView];
if (_currentLiveLocation.isOwn && _mapView.selectedAnnotations.count == 0)
if (_currentLiveLocation.hasOwnSession && _mapView.selectedAnnotations.count == 0)
[_ownLiveLocationView setSelected:true animated:false];
}
}
@@ -869,13 +960,13 @@
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
__weak TGLocationViewController *weakSelf = self;
if (indexPath.row == 0 && ![self isLiveLocation])
{
TGLocationInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:TGLocationInfoCellKind];
if (cell == nil)
cell = [[TGLocationInfoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGLocationInfoCellKind];
__weak TGLocationViewController *weakSelf = self;
[cell setLocation:_locationAttachment messageId:_message.mid userLocationSignal:[self userLocationSignal]];
cell.locatePressed = ^
{
@@ -890,7 +981,7 @@
{
__strong TGLocationViewController *strongSelf = weakSelf;
if (strongSelf != nil)
[strongSelf getDirectionsPressed];
[strongSelf getDirectionsPressed:strongSelf->_locationAttachment prompt:false];
};
return cell;
}
@@ -916,6 +1007,8 @@
{
[cell configureForStart];
}
cell.longPressed = nil;
}
else
{
@@ -927,6 +1020,14 @@
TGLiveLocation *liveLocation = index >= 0 && index < _liveLocations.count ? _liveLocations[index] : nil;
[cell configureWithPeer:liveLocation.peer message:liveLocation.message remaining:self.remainingTimeForMessage(liveLocation.message) userLocationSignal:[self userLocationSignal]];
cell.longPressed = ^
{
__strong TGLocationViewController *strongSelf = weakSelf;
if (strongSelf != nil)
[strongSelf getDirectionsPressed:liveLocation.message.locationAttachment prompt:true];
};
}
return cell;
}
@@ -979,7 +1080,6 @@
{
[[[self userLocationSignal] take:1] startWithNext:^(CLLocation *location)
{
_focusOnOwnLocation = true;
[self _presentLiveLocationMenu:location.coordinate dismissOnCompletion:true];
}];
}
@@ -1108,19 +1208,28 @@
[self setReloadReady:true];
}
- (void)_willStartOwnLiveLocation
{
_focusOnOwnLocation = true;
if (_currentLiveLocation.isOwnLocation)
_ignoreNextUpdates = true;
}
@end
@implementation TGLiveLocation
- (instancetype)initWithMessage:(TGMessage *)message peer:(id)peer isOwn:(bool)isOwn isExpired:(bool)isExpired
- (instancetype)initWithMessage:(TGMessage *)message peer:(id)peer hasOwnSession:(bool)hasOwnSession isOwnLocation:(bool)isOwnLocation isExpired:(bool)isExpired
{
self = [super init];
if (self != nil)
{
_message = message;
_peer = peer;
_isOwn = isOwn;
_hasOwnSession = hasOwnSession;
_isOwnLocation = isOwnLocation;
_isExpired = isExpired;
}
return self;
@@ -1134,7 +1243,8 @@
{
_message = message;
_peer = peer;
_isOwn = true;
_hasOwnSession = true;
_isOwnLocation = true;
_isExpired = false;
}
return self;