Swiftgram/TelegramUI/OpenInOptions.swift
Ilya Laktyushin a1b592611d no message
2018-08-31 00:42:24 +03:00

219 lines
10 KiB
Swift

import UIKit
import TelegramCore
import CoreLocation
import MapKit
enum OpenInItem {
case url(_ url: String)
case location(_ location: TelegramMediaMap, withDirections: Bool)
}
enum OpenInApplication {
case safari
case maps
case other(title: String, identifier: Int64, scheme: String)
}
enum OpenInAction {
case openUrl(_ url: String)
case openLocation(latitude: Double, longitude: Double, withDirections: Bool)
}
final class OpenInOption {
let application: OpenInApplication
let action: () -> OpenInAction
init(application: OpenInApplication, action: @escaping () -> OpenInAction) {
self.application = application
self.action = action
}
var title: String {
get {
switch self.application {
case .safari:
return "Safari"
case .maps:
return "Maps"
case let .other(title, _, _):
return title
}
}
}
}
func availableOpenInOptions(applicationContext: TelegramApplicationContext, item: OpenInItem) -> [OpenInOption] {
return allOpenInOptions(applicationContext: applicationContext, item: item).filter { option in
if case let .other(_, _, scheme) = option.application {
return applicationContext.applicationBindings.canOpenUrl("\(scheme)://")
} else {
return true
}
}
}
private func allOpenInOptions(applicationContext: TelegramApplicationContext, item: OpenInItem) -> [OpenInOption] {
var options: [OpenInOption] = []
switch item {
case let .url(url):
options.append(OpenInOption(application: .safari, action: {
return .openUrl(url)
}))
options.append(OpenInOption(application: .other(title: "Chrome", identifier: 535886823, scheme: "chrome"), action: {
// NSURL *url = (NSURL *)self.object;
// NSString *scheme = [url.scheme lowercaseString];
//
// bool secure = [scheme isEqualToString:@"https"];
// if (!secure && ![scheme isEqualToString:@"http"])
// return;
//
// NSURL *openInURL = nil;
// if (iosMajorVersion() >= 7)
// {
// NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:true];
// components.scheme = secure ? @"googlechromes" : @"googlechrome";
// openInURL = components.URL;
// }
// else
// {
// NSString *str = url.absoluteString;
// NSInteger colon = [str rangeOfString:@":"].location;
// if (colon != NSNotFound)
// str = [(secure ? @"googlechromes" : @"googlechrome") stringByAppendingString:[str substringFromIndex:colon]];
// openInURL = [NSURL URLWithString:str];
// }
return .openUrl(url)
}))
options.append(OpenInOption(application: .other(title: "Firefox", identifier: 989804926, scheme: "firefox"), action: {
// NSURL *url = (NSURL *)self.object;
// NSString *scheme = [url.scheme lowercaseString];
//
// if (![scheme isEqualToString:@"http"] && ![scheme isEqualToString:@"https"])
// return;
//
// NSURL *openInURL = [NSURL URLWithString:[NSString stringWithFormat:@"firefox://open-url?url=%@", [TGStringUtils stringByEscapingForURL:url.absoluteString]]];
// [TGOpenInBrowserItem openURL:openInURL];
return .openUrl(url)
}))
options.append(OpenInOption(application: .other(title: "Opera Mini", identifier: 363729560, scheme: "opera-http"), action: {
// bool secure = [scheme isEqualToString:@"https"];
// if (!secure && ![scheme isEqualToString:@"http"])
// return;
//
// NSURL *openInURL = nil;
// if (iosMajorVersion() >= 7)
// {
// NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:true];
// components.scheme = secure ? @"opera-https" : @"opera-http";
// openInURL = components.URL;
// }
// else
// {
// NSString *str = url.absoluteString;
// NSInteger colon = [str rangeOfString:@":"].location;
// if (colon != NSNotFound)
// str = [(secure ? @"opera-https" : @"opera-http") stringByAppendingString:[str substringFromIndex:colon]];
// openInURL = [NSURL URLWithString:str];
// }
return .openUrl(url)
}))
options.append(OpenInOption(application: .other(title: "Yandex", identifier: 483693909, scheme: "yandexbrowser-open-url"), action: {
// NSURL *url = (NSURL *)self.object;
// NSString *scheme = [url.scheme lowercaseString];
//
// if (![scheme isEqualToString:@"http"] && ![scheme isEqualToString:@"https"])
// return;
//
// NSURL *openInURL = [NSURL URLWithString:[NSString stringWithFormat:@"yandexbrowser-open-url://%@", [TGStringUtils stringByEscapingForURL:url.absoluteString]]];
// [TGOpenInBrowserItem openURL:openInURL];
return .openUrl(url)
}))
case let .location(location, withDirections):
let lat = location.latitude
let lon = location.longitude
if let venue = location.venue, let venueId = venue.id, let provider = venue.provider, provider == "foursquare" {
options.append(OpenInOption(application: .other(title: "Foursquare", identifier: 306934924, scheme: "foursquare"), action: {
return .openUrl("foursquare://venues/\(venueId)")
}))
}
options.append(OpenInOption(application: .maps, action: {
return .openLocation(latitude: lat, longitude: lon, withDirections: withDirections)
}))
options.append(OpenInOption(application: .other(title: "Google Maps", identifier: 585027354, scheme: "comgooglemaps-x-callback"), action: {
let coordinates = "\(lat),\(lon)"
if withDirections {
return .openUrl("comgooglemaps-x-callback://?daddr=\(coordinates)&directionsmode=driving&x-success=telegram://?resume=true&&x-source=Telegram")
} else {
return .openUrl("comgooglemaps-x-callback://?center=\(coordinates)&q=\(coordinates)&x-success=telegram://?resume=true&&x-source=Telegram")
}
}))
options.append(OpenInOption(application: .other(title: "Yandex.Maps", identifier: 313877526, scheme: "yandexmaps"), action: {
if withDirections {
return .openUrl("yandexmaps://build_route_on_map?lat_to=\(lat)&lon_to=\(lon)")
} else {
return .openUrl("yandexmaps://maps.yandex.ru/?pt=\(lat),\(lon)&z=16")
}
}))
options.append(OpenInOption(application: .other(title: "Uber", identifier: 368677368, scheme: "uber"), action: {
var dropoffName = ""
var dropoffAddress = ""
if let title = location.venue?.title.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed), title.count > 0 {
dropoffName = title
}
if let address = location.venue?.address?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed), address.count > 0 {
dropoffAddress = address
}
return .openUrl("uber://?client_id=&action=setPickup&pickup=my_location&dropoff[latitude]=\(lat)&dropoff[longitude]=\(lon)&dropoff[nickname]=\(dropoffName)&dropoff[formatted_address]=\(dropoffAddress)")
}))
options.append(OpenInOption(application: .other(title: "Lyft", identifier: 529379082, scheme: "lyft"), action: {
return .openUrl("lyft://ridetype?id=lyft&destination[latitude]=\(lat)&destination[longitude]=\(lon)")
}))
options.append(OpenInOption(application: .other(title: "Citymapper", identifier: 469463298, scheme: "citymapper"), action: {
var endName = ""
var endAddress = ""
if let title = location.venue?.title.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed), title.count > 0 {
endName = title
}
if let address = location.venue?.address?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed), address.count > 0 {
endAddress = address
}
return .openUrl("citymapper://directions?endcoord=\(lat),\(lon)&endname=\(endName)&endaddress=\(endAddress)")
}))
if withDirections {
options.append(OpenInOption(application: .other(title: "Yandex.Navi", identifier: 474500851, scheme: "yandexnavi"), action: {
return .openUrl("yandexnavi://build_route_on_map?lat_to=\(lat)&lon_to=\(lon)")
}))
}
options.append(OpenInOption(application: .other(title: "HERE Maps", identifier: 955837609, scheme: "here-location"), action: {
return .openUrl("here-location://\(lat),\(lon)")
}))
options.append(OpenInOption(application: .other(title: "Waze", identifier: 323229106, scheme: "waze"), action: {
let url = "waze://?ll=\(lat),\(lon)"
if withDirections {
return .openUrl(url.appending("&navigate=yes"))
} else {
return .openUrl(url)
}
}))
}
return options
}