Skip to content

Commit

Permalink
Add China text localization and fixes #6.
Browse files Browse the repository at this point in the history
  • Loading branch information
faarwa committed Jan 16, 2016
1 parent c9c5df1 commit 7e50439
Show file tree
Hide file tree
Showing 13 changed files with 291 additions and 83 deletions.
8 changes: 4 additions & 4 deletions UberRides.podspec
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
Pod::Spec.new do |s|

s.name = "UberRides"
s.version = "0.1.1"
s.version = "0.2.0"
s.summary = "The Official Uber Rides iOS SDK."
s.description = <<-DESC
This Swift library allows you to integrate Uber into your iOS app. It is designed to make it quick and easy to add a 'Request a Ride' button in your application, seamlessly connecting your users with Uber.
DESC
s.homepage = "https://github.com/uber/rides-ios-sdk"
s.screenshots = "https://raw.githubusercontent.com/uber/rides-ios-sdk/master/img/example_app.png"
s.license = { :type => "MIT", :file => "LICENSE" }
s.author = { "Christine Kim" => "[email protected]" }
s.authors = { "Christine Kim" => "christinek@uber.com", "Farwa Naqi" => "farwa@uber.com" }

s.platform = :ios, "8.0"
s.source = { :git => "https://github.com/uber/rides-ios-sdk.git", :tag => 'v' + s.version.to_s }
s.source = { :git => "https://github.com/uber/rides-ios-sdk.git", :tag => s.version }
s.source_files = "source/UberRides/*.swift"
s.resources = "source/UberRides/Media.xcassets"
s.resource = "source/UberRides/UberRidesResources.bundle/*"
s.requires_arc = true

end
10 changes: 6 additions & 4 deletions source/UberRides.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
AC0404921BFACD7C00AC1501 /* RequestButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC0404911BFACD7C00AC1501 /* RequestButton.swift */; };
AC0404941BFACDAF00AC1501 /* RequestDeeplink.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC0404931BFACDAF00AC1501 /* RequestDeeplink.swift */; };
AC0404961BFACDC900AC1501 /* RidesClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC0404951BFACDC900AC1501 /* RidesClient.swift */; };
AC0404981BFACE0600AC1501 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AC0404971BFACE0600AC1501 /* Media.xcassets */; };
AC04049A1BFACE5400AC1501 /* RequestDeeplinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC0404991BFACE5400AC1501 /* RequestDeeplinkTests.swift */; };
D8F92D9A1C4486E100D65712 /* UberRidesResources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = D8F92D991C4486E100D65712 /* UberRidesResources.bundle */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -39,8 +39,8 @@
AC0404911BFACD7C00AC1501 /* RequestButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestButton.swift; sourceTree = "<group>"; };
AC0404931BFACDAF00AC1501 /* RequestDeeplink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestDeeplink.swift; sourceTree = "<group>"; };
AC0404951BFACDC900AC1501 /* RidesClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RidesClient.swift; sourceTree = "<group>"; };
AC0404971BFACE0600AC1501 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
AC0404991BFACE5400AC1501 /* RequestDeeplinkTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestDeeplinkTests.swift; sourceTree = "<group>"; };
D8F92D991C4486E100D65712 /* UberRidesResources.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = UberRidesResources.bundle; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -89,7 +89,7 @@
AC0404911BFACD7C00AC1501 /* RequestButton.swift */,
AC0404931BFACDAF00AC1501 /* RequestDeeplink.swift */,
AC0404951BFACDC900AC1501 /* RidesClient.swift */,
AC0404971BFACE0600AC1501 /* Media.xcassets */,
D8F92D991C4486E100D65712 /* UberRidesResources.bundle */,
);
path = UberRides;
sourceTree = "<group>";
Expand Down Expand Up @@ -179,6 +179,8 @@
hasScannedForEncodings = 0;
knownRegions = (
en,
"zh-Hans",
"zh-Hant",
);
mainGroup = AC04046B1BFACD1D00AC1501;
productRefGroup = AC0404761BFACD1D00AC1501 /* Products */;
Expand All @@ -196,7 +198,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
AC0404981BFACE0600AC1501 /* Media.xcassets in Resources */,
D8F92D9A1C4486E100D65712 /* UberRidesResources.bundle in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
9 changes: 3 additions & 6 deletions source/UberRides/RequestButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ public class RequestButton: UIButton {

let clientID = RidesClient.sharedInstance.clientID
deeplink = RequestDeeplink(withClientID: clientID!, fromSource: .Button)
deeplink!.build()
}

/**
Expand All @@ -91,7 +90,6 @@ public class RequestButton: UIButton {
public func setPickupLocationToCurrentLocation() {
if RidesClient.sharedInstance.hasClientID() {
deeplink!.setPickupLocationToCurrentLocation()
deeplink!.build()
}
}

Expand All @@ -106,7 +104,6 @@ public class RequestButton: UIButton {
public func setPickupLocation(latitude lat: String, longitude: String, nickname: String? = nil, address: String? = nil) {
if RidesClient.sharedInstance.hasClientID() {
deeplink!.setPickupLocation(latitude: lat, longitude: longitude, nickname: nickname, address: address)
deeplink!.build()
}
}

Expand All @@ -121,7 +118,6 @@ public class RequestButton: UIButton {
public func setDropoffLocation(latitude lat: String, longitude: String, nickname: String? = nil, address: String? = nil) {
if RidesClient.sharedInstance.hasClientID() {
deeplink!.setDropoffLocation(latitude: lat, longitude: longitude, nickname: nickname, address: address)
deeplink!.build()
}
}

Expand All @@ -134,14 +130,14 @@ public class RequestButton: UIButton {
public func setProductID(productID: String) {
if RidesClient.sharedInstance.hasClientID() {
deeplink!.setProductID(productID)
deeplink!.build()
}
}

// add title, image, and sizing configuration
private func setContent() {
// add title label
uberTitleLabel.text = "Ride there with Uber"
let bundle = NSBundle(forClass: RequestButton.self)
uberTitleLabel.text = NSLocalizedString("RequestButton.TitleText", bundle: bundle, comment: "Request button description")
uberTitleLabel.font = UIFont.systemFontOfSize(17)
uberTitleLabel.numberOfLines = 1;

Expand Down Expand Up @@ -238,6 +234,7 @@ public class RequestButton: UIButton {
// initiate deeplink when button is tapped
public func uberButtonTapped(sender: UIButton) {
if RidesClient.sharedInstance.hasClientID() {
deeplink!.build()
deeplink!.execute()
}
}
Expand Down
124 changes: 80 additions & 44 deletions source/UberRides/RequestDeeplink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ import UIKit

// RequestDeeplink builds and executes a deeplink to the native Uber app.
public class RequestDeeplink: NSObject {
private var parameters: [QueryParameter]
private var parameters: QueryParameters
private var clientID: String
private var deeplinkURI: String?
private var source: RequestDeeplink.SourceParameter

public init(withClientID: String, fromSource: SourceParameter = .Deeplink) {
parameters = QueryParameters()
clientID = withClientID
source = fromSource
parameters = [QueryParameter(parameterName: .ClientID, parameterValue: clientID)]
parameters.setParameter(.ClientID, parameterValue: clientID)
}

/**
Expand All @@ -47,12 +48,18 @@ public class RequestDeeplink: NSObject {
setPickupLocationToCurrentLocation()
}

let deeplink = "uber://?"
var parameterStrings: [String] = []
for parameter in parameters {
parameterStrings.append(parameter.toString())
if !parameters.pendingChanges {
return deeplinkURI!
}
deeplinkURI = deeplink + parameterStrings.joinWithSeparator("&")

let components = NSURLComponents()
components.scheme = "uber"
components.host = ""
components.queryItems = parameters.getQueryItems()

parameters.pendingChanges = false;

deeplinkURI = components.string?.stringByRemovingPercentEncoding
return deeplinkURI!
}

Expand All @@ -74,38 +81,42 @@ public class RequestDeeplink: NSObject {
Set the user's current location as a default pickup location.
*/
public func setPickupLocationToCurrentLocation() {
parameters.append(QueryParameter(parameterName: .Action, parameterValue: "setPickup"))
parameters.append(QueryParameter(parameterName: .PickupDefault, parameterValue: "my_location"))
parameters.setParameter(.Action, parameterValue: "setPickup")
parameters.setParameter(.PickupDefault, parameterValue: "my_location")
parameters.deleteParameters([.PickupLatitude, .PickupLongitude, .PickupAddress, .PickupNickname])
}

/**
Set deeplink pickup location information.
*/
public func setPickupLocation(latitude lat: String, longitude: String, nickname: String? = nil, address: String? = nil) {
parameters.append(QueryParameter(parameterName: .Action, parameterValue: "setPickup"))
parameters.append(QueryParameter(parameterName: .PickupLatitude, parameterValue: lat))
parameters.append(QueryParameter(parameterName: .PickupLongitude, parameterValue: longitude))
parameters.deleteParameters([.PickupNickname, .PickupAddress])
parameters.setParameter(.Action, parameterValue: "setPickup")
parameters.setParameter(.PickupLatitude, parameterValue: lat)
parameters.setParameter(.PickupLongitude, parameterValue: longitude)

if nickname != nil {
parameters.append(QueryParameter(parameterName: .PickupNickname, parameterValue: nickname!))
parameters.setParameter(.PickupNickname, parameterValue: nickname!)
}
if address != nil {
parameters.append(QueryParameter(parameterName: .PickupAddress, parameterValue: address!))
parameters.setParameter(.PickupAddress, parameterValue: address!)
}

parameters.deleteParameters([.PickupDefault])
}

/**
Set deeplink dropoff location information.
*/
public func setDropoffLocation(latitude lat: String, longitude: String, nickname: String? = nil, address: String? = nil) {
parameters.append(QueryParameter(parameterName: .DropoffLatitude, parameterValue: lat))
parameters.append(QueryParameter(parameterName: .DropoffLongitude, parameterValue: longitude))
parameters.setParameter(.DropoffLatitude, parameterValue: lat)
parameters.setParameter(.DropoffLongitude, parameterValue: longitude)

if nickname != nil {
parameters.append(QueryParameter(parameterName: .DropoffNickname, parameterValue: nickname!))
parameters.setParameter(.DropoffNickname, parameterValue: nickname!)
}
if address != nil {
parameters.append(QueryParameter(parameterName: .DropoffAddress, parameterValue: address!))
parameters.setParameter(.DropoffAddress, parameterValue: address!)
}
}

Expand All @@ -114,25 +125,14 @@ public class RequestDeeplink: NSObject {
location with the Rides API `GET /v1/products` endpoint.
*/
public func setProductID(productID: String) {
parameters.append(QueryParameter(parameterName: .ProductID, parameterValue: productID))
parameters.setParameter(.ProductID, parameterValue: productID)
}

/**
Return true if deeplink has set pickup latitude and longitude, false otherwise.
*/
internal func pickupLocationSet() -> Bool {
var hasLatitude = false
var hasLongitude = false

for parameter in parameters {
if parameter.name == .PickupLatitude {
hasLatitude = true
} else if parameter.name == .PickupLongitude {
hasLongitude = true
}
}

return (hasLatitude && hasLongitude)
return (parameters.doesParameterExist(.PickupLatitude) && parameters.doesParameterExist(.PickupLongitude)) || parameters.doesParameterExist(.PickupDefault)
}

/**
Expand All @@ -158,8 +158,14 @@ public class RequestDeeplink: NSObject {
}


// Store information about the name and value of a query parameter.
private class QueryParameter: NSObject {
// Store mapping of parameter names to values
private class QueryParameters: NSObject {
private var params = [String: String]()
private var pendingChanges: Bool

private override init() {
pendingChanges = false;
}

/**
QueryParameterName is a set of query parameters than can be sent
Expand All @@ -183,22 +189,47 @@ private class QueryParameter: NSObject {
case DropoffAddress
}

private let name: QueryParameterName
private let value: String
/**
Adds a query parameter. If parameterName has already been assigned a value,
its overwritten with parameterValue.
*/
private func setParameter(parameterName: QueryParameterName, parameterValue: String) {
params[stringFromParameterName(parameterName)] = stringFromParameterValue(parameterValue)
pendingChanges = true
}

private init(parameterName: QueryParameterName, parameterValue: String) {
name = parameterName
value = parameterValue
super.init()
/**
Removes key-value pair of all query parameters in array of parameter names.
*/
private func deleteParameters(parameters: Array<QueryParameterName>) {
for name in parameters {
params.removeValueForKey(stringFromParameterName(name))
}
pendingChanges = true
}

private func toString() -> String {
let customAllowedChars = NSCharacterSet(charactersInString: " =\"#%/<>?@\\^`{|}!$&'()*+,:;[]%").invertedSet
let stringFromParameterValue = value.stringByAddingPercentEncodingWithAllowedCharacters(customAllowedChars)!
return "\(stringFromParameterName())=\(stringFromParameterValue)"
/**
- returns: An array containing an NSURLQueryItem for every parameter
*/
private func getQueryItems() -> Array<NSURLQueryItem> {
var queryItems = [NSURLQueryItem]()

for (parameterName, parameterValue) in params {
let queryItem = NSURLQueryItem(name: parameterName, value: parameterValue)
queryItems.append(queryItem)
}

return queryItems
}

private func stringFromParameterName() -> String {
/**
- returns: true if given query parameter has been set; false otherwise.
*/
private func doesParameterExist(parameterName: QueryParameterName) -> Bool {
return params[stringFromParameterName(parameterName)] != nil
}

private func stringFromParameterName(name: QueryParameterName) -> String {
switch name {
case .Action:
return "action"
Expand Down Expand Up @@ -226,4 +257,9 @@ private class QueryParameter: NSObject {
return "dropoff[formatted_address]"
}
}

private func stringFromParameterValue(value: String) -> String {
let customAllowedChars = NSCharacterSet(charactersInString: " =\"#%/<>?@\\^`{|}!$&'()*+,:;[]%").invertedSet
return value.stringByAddingPercentEncodingWithAllowedCharacters(customAllowedChars)!
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "uber_badge_24.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "[email protected]",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "[email protected]",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* The title of the request button that deep links to the Uber app */
"RequestButton.TitleText" = "Ride there with Uber";
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* The title of the request button that deep links to the Uber app */
"RequestButton.TitleText" = "搭乘优步前往";
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* The title of the request button that deep links to the Uber app */
"RequestButton.TitleText" = "搭乘优步前往";
Loading

0 comments on commit 7e50439

Please sign in to comment.