Improve venue colors

This commit is contained in:
Ilya Laktyushin 2019-11-25 19:01:11 +04:00
parent 1884c63bed
commit 4baf8ddbf9
12 changed files with 122 additions and 45 deletions

View File

@ -19,6 +19,7 @@
@property (nonatomic, readonly) TGLocationMediaAttachment *location;
@property (nonatomic, readonly) bool isLiveLocation;
@property (nonatomic, strong) id peer;
@property (nonatomic, strong) UIColor *color;
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, assign) int32_t messageId;
@property (nonatomic, assign) bool isOwn;
@ -26,5 +27,6 @@
@property (nonatomic, assign) bool isExpired;
- (instancetype)initWithLocation:(TGLocationMediaAttachment *)location;
- (instancetype)initWithLocation:(TGLocationMediaAttachment *)location color:(UIColor *)color;
@end

View File

@ -30,11 +30,17 @@
}
- (instancetype)initWithLocation:(TGLocationMediaAttachment *)location
{
return [self initWithLocation:location color:nil];
}
- (instancetype)initWithLocation:(TGLocationMediaAttachment *)location color:(UIColor *)color
{
self = [super init];
if (self != nil)
{
_coordinate = CLLocationCoordinate2DMake(location.latitude, location.longitude);
_color = color;
_location = location;
_observers = [[NSMutableSet alloc] init];
}

View File

@ -14,7 +14,7 @@
@property (nonatomic, readonly) UIButton *directionsButton;
- (void)setLocation:(TGLocationMediaAttachment *)location messageId:(int32_t)messageId userLocationSignal:(SSignal *)userLocationSignal;
- (void)setLocation:(TGLocationMediaAttachment *)location color:(UIColor *)color messageId:(int32_t)messageId userLocationSignal:(SSignal *)userLocationSignal;
@end

View File

@ -158,7 +158,7 @@ const CGFloat TGLocationInfoCellHeight = 134.0f;
return _directionsButton;
}
- (void)setLocation:(TGLocationMediaAttachment *)location messageId:(int32_t)messageId userLocationSignal:(SSignal *)userLocationSignal
- (void)setLocation:(TGLocationMediaAttachment *)location color:(UIColor *)color messageId:(int32_t)messageId userLocationSignal:(SSignal *)userLocationSignal
{
if (_messageId == messageId)
return;
@ -167,6 +167,10 @@ const CGFloat TGLocationInfoCellHeight = 134.0f;
_titleLabel.text = location.venue.title.length > 0 ? location.venue.title : TGLocalized(@"Map.Location");
if (color != nil) {
[_circleView setImage:TGTintedImage([TGLocationVenueCell circleImage], color)];
}
if (location.venue.type.length > 0 && [location.venue.provider isEqualToString:@"foursquare"])
[_iconView loadUri:[NSString stringWithFormat:@"location-venue-icon://type=%@&width=%d&height=%d&color=%d", location.venue.type, 48, 48, TGColorHexCode(_pallete != nil ? _pallete.iconColor : [UIColor whiteColor])] withOptions:nil];

View File

@ -265,7 +265,12 @@ NSString *const TGLocationPinAnnotationKind = @"TGLocationPinAnnotation";
_avatarView.alpha = 1.0f;
_iconView.hidden = false;
_backgroundView.image = TGTintedImage(TGComponentsImageNamed(@"LocationPinBackground"), _pallete != nil ? _pallete.locationColor : UIColorRGB(0x008df2));
UIColor *color = _pallete != nil ? _pallete.locationColor : UIColorRGB(0x008df2);
if (locationAnnotation.color != nil) {
color = locationAnnotation.color;
}
_backgroundView.image = TGTintedImage(TGComponentsImageNamed(@"LocationPinBackground"), color);
if (location.venue.type.length > 0)
{
[_iconView loadUri:[NSString stringWithFormat:@"location-venue-icon://type=%@&width=%d&height=%d&color=%d", location.venue.type, 64, 64, TGColorHexCode(_pallete != nil ? _pallete.iconColor : [UIColor whiteColor])] withOptions:nil];

View File

@ -48,8 +48,8 @@
@property (nonatomic, copy) SSignal *(^remainingTimeForMessage)(TGMessage *message);
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context liveLocation:(TGLiveLocation *)liveLocation;
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context locationAttachment:(TGLocationMediaAttachment *)locationAttachment peer:(id)peer;
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context message:(TGMessage *)message peer:(id)peer;
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context locationAttachment:(TGLocationMediaAttachment *)locationAttachment peer:(id)peer color:(UIColor *)color;
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context message:(TGMessage *)message peer:(id)peer color:(UIColor *)color;
- (void)actionsButtonPressed;

View File

@ -43,6 +43,7 @@
id _peer;
TGMessage *_message;
TGLocationMediaAttachment *_locationAttachment;
UIColor *_venueColor;
TGLocationAnnotation *_annotation;
@ -75,12 +76,13 @@
@implementation TGLocationViewController
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context locationAttachment:(TGLocationMediaAttachment *)locationAttachment peer:(id)peer
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context locationAttachment:(TGLocationMediaAttachment *)locationAttachment peer:(id)peer color:(UIColor *)color
{
self = [self initWithContext:context];
if (self != nil)
{
_locationAttachment = locationAttachment;
_venueColor = color;
_reloadDisposable = [[SMetaDisposable alloc] init];
_reloadReady = [[SVariable alloc] init];
@ -90,7 +92,7 @@
_peer = peer;
if (locationAttachment.period == 0)
_annotation = [[TGLocationAnnotation alloc] initWithLocation:locationAttachment];
_annotation = [[TGLocationAnnotation alloc] initWithLocation:locationAttachment color:color];
_liveLocationsDisposable = [[SMetaDisposable alloc] init];
@ -128,7 +130,7 @@
return self;
}
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context message:(TGMessage *)message peer:(id)peer
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context message:(TGMessage *)message peer:(id)peer color:(UIColor *)color
{
self = [self initWithContext:context];
if (self != nil)
@ -142,9 +144,10 @@
_context = context;
_peer = peer;
_venueColor = color;
if (_locationAttachment.period == 0)
_annotation = [[TGLocationAnnotation alloc] initWithLocation:_locationAttachment];
_annotation = [[TGLocationAnnotation alloc] initWithLocation:_locationAttachment color:color];
_liveLocationsDisposable = [[SMetaDisposable alloc] init];
@ -1005,7 +1008,7 @@
if (cell == nil)
cell = [[TGLocationInfoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGLocationInfoCellKind];
cell.pallete = self.pallete;
[cell setLocation:_locationAttachment messageId:_message.mid userLocationSignal:[self userLocationSignal]];
[cell setLocation:_locationAttachment color: _venueColor messageId:_message.mid userLocationSignal:[self userLocationSignal]];
cell.locatePressed = ^
{
__strong TGLocationViewController *strongSelf = weakSelf;

View File

@ -114,12 +114,39 @@ private func venueIconData(postbox: Postbox, resource: MediaResource) -> Signal<
return signal
}
private let colors = [UIColor(rgb: 0xe56cd5), UIColor(rgb: 0xf89440), UIColor(rgb: 0x9986ff), UIColor(rgb: 0x44b3f5), UIColor(rgb: 0x6dc139), UIColor(rgb: 0xff5d5a), UIColor(rgb: 0xf87aad), UIColor(rgb: 0x6e82b3), UIColor(rgb: 0xf5ba21)]
private let randomColors = [UIColor(rgb: 0xe56cd5), UIColor(rgb: 0xf89440), UIColor(rgb: 0x9986ff), UIColor(rgb: 0x44b3f5), UIColor(rgb: 0x6dc139), UIColor(rgb: 0xff5d5a), UIColor(rgb: 0xf87aad), UIColor(rgb: 0x6e82b3), UIColor(rgb: 0xf5ba21)]
private let venueColors: [String: UIColor] = [
"building/medical": UIColor(rgb: 0x43b3f4),
"building/gym": UIColor(rgb: 0x43b3f4),
"arts_entertainment": UIColor(rgb: 0xe56dd6),
"travel/bedandbreakfast": UIColor(rgb: 0x9987ff),
"travel/hotel": UIColor(rgb: 0x9987ff),
"travel/hostel": UIColor(rgb: 0x9987ff),
"travel/resort": UIColor(rgb: 0x9987ff),
"building": UIColor(rgb: 0x6e81b2),
"education": UIColor(rgb: 0xa57348),
"event": UIColor(rgb: 0x959595),
"food": UIColor(rgb: 0xf7943f),
"education/cafeteria": UIColor(rgb: 0xf7943f),
"nightlife": UIColor(rgb: 0xe56dd6),
"travel/hotel_bar": UIColor(rgb: 0xe56dd6),
"parks_outdoors": UIColor(rgb: 0x6cc039),
"shops": UIColor(rgb: 0xffb300),
"travel": UIColor(rgb: 0x1c9fff),
]
public func venueIconColor(type: String) -> UIColor {
let parentType = type.components(separatedBy: "/").first ?? type
let index = Int(abs(persistentHash32(parentType)) % Int32(colors.count))
return colors[index]
if let color = venueColors[type] {
return color
}
let generalType = type.components(separatedBy: "/").first ?? type
if let color = venueColors[generalType] {
return color
}
let index = Int(abs(persistentHash32(type)) % Int32(randomColors.count))
return randomColors[index]
}
public func venueIcon(postbox: Postbox, type: String, background: Bool) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {

View File

@ -11,6 +11,7 @@ import ShareController
import LegacyUI
import OpenInExternalAppUI
import AppBundle
import LocationResources
private func generateClearIcon(color: UIColor) -> UIImage? {
return generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: color)
@ -142,6 +143,7 @@ public func legacyLocationController(message: Message?, mapMedia: TelegramMediaM
legacyController.navigationPresentation = .modal
let controller: TGLocationViewController
let venueColor = mapMedia.venue?.type.flatMap { venueIconColor(type: $0) }
if let message = message {
let legacyMessage = makeLegacyMessage(message)
let legacyAuthor: AnyObject? = message.author.flatMap(makeLegacyPeer)
@ -201,7 +203,7 @@ public func legacyLocationController(message: Message?, mapMedia: TelegramMediaM
controller.setLiveLocationsSignal(updatedLocations)
}
} else {
controller = TGLocationViewController(context: legacyController.context, message: legacyMessage, peer: legacyAuthor)!
controller = TGLocationViewController(context: legacyController.context, message: legacyMessage, peer: legacyAuthor, color: venueColor)!
controller.receivingPeer = message.peers[message.id.peerId].flatMap(makeLegacyPeer)
controller.setLiveLocationsSignal(updatedLocations)
}
@ -218,7 +220,7 @@ public func legacyLocationController(message: Message?, mapMedia: TelegramMediaM
let attachment = TGLocationMediaAttachment()
attachment.latitude = mapMedia.latitude
attachment.longitude = mapMedia.longitude
controller = TGLocationViewController(context: legacyController.context, locationAttachment: attachment, peer: nil)
controller = TGLocationViewController(context: legacyController.context, locationAttachment: attachment, peer: nil, color: venueColor)
}
controller.remainingTimeForMessage = { message in

View File

@ -112,7 +112,7 @@ final class LocationMapHeaderNode: ASDisplayNode {
transition.updateFrame(node: self.locationButtonNode, frame: CGRect(x: panelInset, y: panelInset + panelSize.height / 2.0, width: panelSize.width, height: panelSize.height / 2.0))
let alphaTransition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
let optionsAlpha: CGFloat = size.height > 110.0 + navigationBarHeight ? 1.0 : 0.0
let optionsAlpha: CGFloat = size.height > 124.0 + navigationBarHeight ? 1.0 : 0.0
alphaTransition.updateAlpha(node: self.optionsBackgroundNode, alpha: optionsAlpha)
}

View File

@ -20,17 +20,13 @@ class LocationPickerInteraction {
let sendLocation: (CLLocationCoordinate2D) -> Void
let sendLiveLocation: (CLLocationCoordinate2D) -> Void
let sendVenue: (TelegramMediaMap) -> Void
let toggleMapModeSelection: () -> Void
let updateMapMode: (LocationMapMode) -> Void
let goToUserLocation: () -> Void
let openSearch: () -> Void
let updateSearchQuery: (String) -> Void
let dismissSearch: () -> Void
let dismissInput: () -> Void
let updateSendActionHighlight: (Bool) -> Void
init(sendLocation: @escaping (CLLocationCoordinate2D) -> Void, sendLiveLocation: @escaping (CLLocationCoordinate2D) -> Void, sendVenue: @escaping (TelegramMediaMap) -> Void, toggleMapModeSelection: @escaping () -> Void, updateMapMode: @escaping (LocationMapMode) -> Void, goToUserLocation: @escaping () -> Void, openSearch: @escaping () -> Void, updateSearchQuery: @escaping (String) -> Void, dismissSearch: @escaping () -> Void, dismissInput: @escaping () -> Void, updateSendActionHighlight: @escaping (Bool) -> Void) {
@ -63,11 +59,6 @@ public final class LocationPickerController: ViewController {
private var interaction: LocationPickerInteraction?
private let _ready = Promise<Bool>()
override public var ready: Promise<Bool> {
return self._ready
}
public init(context: AccountContext, mode: LocationPickerMode, completion: @escaping (TelegramMediaMap, String?) -> Void) {
self.context = context
self.mode = mode
@ -227,6 +218,8 @@ public final class LocationPickerController: ViewController {
strongSelf.controllerNode.scrollToTop()
}
}
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
}
required public init(coder aDecoder: NSCoder) {
@ -238,14 +231,13 @@ public final class LocationPickerController: ViewController {
}
override public func loadDisplayNode() {
super.loadDisplayNode()
guard let interaction = self.interaction else {
return
}
self.displayNode = LocationPickerControllerNode(context: self.context, presentationData: self.presentationData, mode: self.mode, interaction: interaction)
self.displayNodeDidLoad()
self._ready.set(.single(true))
}
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {

View File

@ -21,6 +21,7 @@ private struct LocationPickerTransaction {
let insertions: [ListViewInsertItem]
let updates: [ListViewUpdateItem]
let isLoading: Bool
let crossFade: Bool
}
private enum LocationPickerEntryId: Hashable {
@ -159,17 +160,17 @@ private enum LocationPickerEntry: Comparable, Identifiable {
}
}
private func preparedTransition(from fromEntries: [LocationPickerEntry], to toEntries: [LocationPickerEntry], isLoading: Bool, account: Account, presentationData: PresentationData, interaction: LocationPickerInteraction?) -> LocationPickerTransaction {
private func preparedTransition(from fromEntries: [LocationPickerEntry], to toEntries: [LocationPickerEntry], isLoading: Bool, crossFade: Bool, account: Account, presentationData: PresentationData, interaction: LocationPickerInteraction?) -> LocationPickerTransaction {
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
return LocationPickerTransaction(deletions: deletions, insertions: insertions, updates: updates, isLoading: isLoading)
return LocationPickerTransaction(deletions: deletions, insertions: insertions, updates: updates, isLoading: isLoading, crossFade: crossFade)
}
enum LocationPickerLocation {
enum LocationPickerLocation: Equatable {
case none
case selecting
case location(CLLocationCoordinate2D, String?)
@ -177,10 +178,40 @@ enum LocationPickerLocation {
var isCustom: Bool {
switch self {
case .none:
return false
default:
case .selecting, .location:
return true
default:
return false
}
}
public static func ==(lhs: LocationPickerLocation, rhs: LocationPickerLocation) -> Bool {
switch lhs {
case .none:
if case .none = rhs {
return true
} else {
return false
}
case .selecting:
if case .selecting = rhs {
return true
} else {
return false
}
case let .location(lhsCoordinate, lhsAddress):
if case let .location(rhsCoordinate, rhsAddress) = rhs, lhsCoordinate == rhsCoordinate, lhsAddress == rhsAddress {
return true
} else {
return false
}
case let .venue(lhsVenue):
if case let .venue(rhsVenue) = rhs, lhsVenue.venue?.id == rhsVenue.venue?.id {
return true
} else {
return false
}
}
}
}
@ -211,7 +242,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
private let optionsNode: LocationOptionsNode
private(set) var searchContainerNode: LocationSearchContainerNode?
private var enqueuedTransitions: [(LocationPickerTransaction, Bool)] = []
private var enqueuedTransitions: [LocationPickerTransaction] = []
private var disposable: Disposable?
private var state: LocationPickerState
@ -232,6 +263,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
self.statePromise = Promise(self.state)
self.listNode = ListView()
self.listNode.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
self.listNode.verticalScrollIndicatorColor = UIColor(white: 0.0, alpha: 0.3)
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
@ -332,8 +364,15 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
}
}
let previousEntries = previousEntries.swap(entries)
let transition = preparedTransition(from: previousEntries ?? [], to: entries, isLoading: venues == nil, account: context.account, presentationData: presentationData, interaction: strongSelf.interaction)
strongSelf.enqueueTransition(transition, firstTime: false)
let previousState = previousState.swap(state)
var crossFade = false
if previousEntries?.count != entries.count || previousState.selectedLocation != state.selectedLocation {
crossFade = true
}
let transition = preparedTransition(from: previousEntries ?? [], to: entries, isLoading: venues == nil, crossFade: crossFade, account: context.account, presentationData: presentationData, interaction: strongSelf.interaction)
strongSelf.enqueueTransition(transition)
strongSelf.headerNode.updateState(state)
@ -363,8 +402,6 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
strongSelf.headerNode.mapNode.annotations = annotations
}
let previousState = previousState.swap(state)
if let (layout, navigationBarHeight) = strongSelf.validLayout {
var updateLayout = false
var transition: ContainedViewLayoutTransition = .animated(duration: 0.45, curve: .spring)
@ -473,6 +510,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
self.presentationDataPromise.set(.single(presentationData))
self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
self.listNode.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
self.headerNode.updatePresentationData(self.presentationData)
self.optionsNode.updatePresentationData(self.presentationData)
self.searchContainerNode?.updatePresentationData(self.presentationData)
@ -483,8 +521,8 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
self.statePromise.set(.single(self.state))
}
private func enqueueTransition(_ transition: LocationPickerTransaction, firstTime: Bool) {
self.enqueuedTransitions.append((transition, firstTime))
private func enqueueTransition(_ transition: LocationPickerTransaction) {
self.enqueuedTransitions.append(transition)
if let _ = self.validLayout {
while !self.enqueuedTransitions.isEmpty {
@ -494,15 +532,13 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
}
private func dequeueTransition() {
guard let layout = self.validLayout, let (transition, firstTime) = self.enqueuedTransitions.first else {
guard let layout = self.validLayout, let transition = self.enqueuedTransitions.first else {
return
}
self.enqueuedTransitions.remove(at: 0)
var options = ListViewDeleteAndInsertOptions()
if firstTime {
options.insert(.PreferSynchronousDrawing)
} else {
if transition.crossFade {
options.insert(.AnimateCrossfade)
}