bubble-wrap 1.1.5 → 1.2.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.travis.yml +2 -0
- data/CHANGELOG.md +25 -1
- data/Gemfile.lock +1 -1
- data/README.md +126 -5
- data/lib/bubble-wrap/all.rb +1 -1
- data/lib/bubble-wrap/camera.rb +2 -1
- data/lib/bubble-wrap/core.rb +1 -2
- data/lib/bubble-wrap/font.rb +2 -0
- data/lib/bubble-wrap/location.rb +2 -0
- data/lib/bubble-wrap/version.rb +1 -1
- data/motion/core/app.rb +17 -0
- data/motion/core/device/camera.rb +5 -25
- data/motion/font/font.rb +85 -0
- data/motion/http.rb +32 -12
- data/motion/location/location.rb +19 -17
- data/motion/reactor.rb +7 -2
- data/motion/reactor/eventable.rb +14 -4
- data/motion/reactor/periodic_timer.rb +9 -3
- data/motion/ui/ui_bar_button_item.rb +99 -0
- data/motion/util/constants.rb +38 -0
- data/resources/test.mp3 +0 -0
- data/samples/camera/Gemfile +1 -1
- data/samples/camera/app/app_delegate.rb +1 -1
- data/samples/camera/app/controllers/camera_controller.rb +32 -47
- data/spec/motion/core/app_spec.rb +24 -0
- data/spec/motion/core/ui_bar_button_item_spec.rb +454 -0
- data/spec/motion/font/font_spec.rb +54 -0
- data/spec/motion/http_spec.rb +83 -9
- data/spec/motion/location/location_spec.rb +22 -1
- data/spec/motion/reactor/eventable_spec.rb +15 -0
- data/spec/motion/reactor_spec.rb +32 -0
- data/spec/motion/util/constants_spec.rb +26 -0
- metadata +24 -18
data/motion/http.rb
CHANGED
@@ -34,6 +34,7 @@ module BubbleWrap
|
|
34
34
|
attr_reader :headers
|
35
35
|
attr_accessor :status_code, :status_description, :error_message
|
36
36
|
attr_reader :url
|
37
|
+
attr_reader :original_url
|
37
38
|
|
38
39
|
def initialize(values={})
|
39
40
|
self.update(values)
|
@@ -86,6 +87,7 @@ module BubbleWrap
|
|
86
87
|
# a proc will receive a Response object while the passed object
|
87
88
|
# will receive the handle_query_response method
|
88
89
|
# :headers<Hash> - headers send with the request
|
90
|
+
# :cookies<Boolean> - Set whether cookies should be sent with request or not (Default: true)
|
89
91
|
# Anything else will be available via the options attribute reader.
|
90
92
|
#
|
91
93
|
def initialize(url_string, http_method = :get, options={})
|
@@ -101,17 +103,20 @@ module BubbleWrap
|
|
101
103
|
@format = options.delete(:format)
|
102
104
|
@cache_policy = options.delete(:cache_policy) || NSURLRequestUseProtocolCachePolicy
|
103
105
|
@credential_persistence = options.delete(:credential_persistence) || NSURLCredentialPersistenceForSession
|
106
|
+
@cookies = options.key?(:cookies) ? options.delete(:cookies) : true
|
104
107
|
@options = options
|
105
108
|
@response = HTTP::Response.new
|
109
|
+
@follow_urls = options[:follow_urls] || true
|
106
110
|
|
107
111
|
@url = create_url(url_string)
|
108
112
|
@body = create_request_body
|
109
113
|
@request = create_request
|
114
|
+
@original_url = @url.copy
|
110
115
|
|
111
116
|
@connection = create_connection(request, self)
|
112
117
|
@connection.start
|
113
118
|
|
114
|
-
UIApplication.sharedApplication.networkActivityIndicatorVisible = true
|
119
|
+
UIApplication.sharedApplication.networkActivityIndicatorVisible = true if defined?(UIApplication)
|
115
120
|
end
|
116
121
|
|
117
122
|
def to_s
|
@@ -137,6 +142,10 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
|
|
137
142
|
end
|
138
143
|
|
139
144
|
def connection(connection, willSendRequest:request, redirectResponse:redirect_response)
|
145
|
+
# abort early if the user has explicitly disabled redirects
|
146
|
+
if @options[:no_redirect] and redirect_response then
|
147
|
+
return nil
|
148
|
+
end
|
140
149
|
@redirect_count ||= 0
|
141
150
|
@redirect_count += 1
|
142
151
|
log "##{@redirect_count} HTTP redirect_count: #{request.inspect} - #{self.description}"
|
@@ -147,13 +156,14 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
|
|
147
156
|
call_delegator_with_response
|
148
157
|
nil
|
149
158
|
else
|
159
|
+
@url = request.URL if @follow_urls
|
150
160
|
request
|
151
161
|
end
|
152
162
|
end
|
153
163
|
|
154
164
|
def connection(connection, didFailWithError: error)
|
155
|
-
log "HTTP Connection failed #{error.localizedDescription}"
|
156
|
-
UIApplication.sharedApplication.networkActivityIndicatorVisible = false
|
165
|
+
log "HTTP Connection to #{@url.absoluteString} failed #{error.localizedDescription}"
|
166
|
+
UIApplication.sharedApplication.networkActivityIndicatorVisible = false if defined?(UIApplication)
|
157
167
|
@request.done_loading!
|
158
168
|
@response.error_message = error.localizedDescription
|
159
169
|
call_delegator_with_response
|
@@ -166,10 +176,10 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
|
|
166
176
|
end
|
167
177
|
|
168
178
|
def connectionDidFinishLoading(connection)
|
169
|
-
UIApplication.sharedApplication.networkActivityIndicatorVisible = false
|
179
|
+
UIApplication.sharedApplication.networkActivityIndicatorVisible = false if defined?(UIApplication)
|
170
180
|
@request.done_loading!
|
171
181
|
response_body = NSData.dataWithData(@received_data) if @received_data
|
172
|
-
@response.update(status_code: status_code, body: response_body, headers: response_headers, url: @url)
|
182
|
+
@response.update(status_code: status_code, body: response_body, headers: response_headers, url: @url, original_url: @original_url)
|
173
183
|
|
174
184
|
call_delegator_with_response
|
175
185
|
end
|
@@ -203,6 +213,7 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
|
|
203
213
|
set_content_type
|
204
214
|
request.setAllHTTPHeaderFields(@headers)
|
205
215
|
request.setHTTPBody(@body)
|
216
|
+
request.setHTTPShouldHandleCookies(@cookies)
|
206
217
|
patch_nsurl_request(request)
|
207
218
|
|
208
219
|
request
|
@@ -260,26 +271,34 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
|
|
260
271
|
def append_form_params(body)
|
261
272
|
list = process_payload_hash(@payload)
|
262
273
|
list.each do |key, value|
|
263
|
-
form_data = NSMutableData.new
|
264
274
|
s = "--#{@boundary}\r\n"
|
265
275
|
s += "Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n"
|
266
276
|
s += value.to_s
|
267
277
|
s += "\r\n"
|
268
|
-
|
269
|
-
body.appendData(form_data)
|
278
|
+
body.appendData(s.dataUsingEncoding NSUTF8StringEncoding)
|
270
279
|
end
|
271
280
|
@payload_or_files_were_appended = true
|
272
281
|
body
|
273
282
|
end
|
274
283
|
|
284
|
+
def parse_file(key, value)
|
285
|
+
if value.is_a?(Hash)
|
286
|
+
raise InvalidFileError if value[:data].nil?
|
287
|
+
{data: value[:data], filename: value[:filename] || key}
|
288
|
+
else
|
289
|
+
{data: value, filename: key}
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
275
293
|
def append_files(body)
|
276
294
|
@files.each do |key, value|
|
277
|
-
|
295
|
+
file = parse_file(key, value)
|
278
296
|
s = "--#{@boundary}\r\n"
|
279
|
-
s += "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{
|
297
|
+
s += "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{file[:filename]}\"\r\n"
|
280
298
|
s += "Content-Type: application/octet-stream\r\n\r\n"
|
299
|
+
file_data = NSMutableData.new
|
281
300
|
file_data.appendData(s.dataUsingEncoding NSUTF8StringEncoding)
|
282
|
-
file_data.appendData(
|
301
|
+
file_data.appendData(file[:data])
|
283
302
|
file_data.appendData("\r\n".dataUsingEncoding NSUTF8StringEncoding)
|
284
303
|
body.appendData(file_data)
|
285
304
|
end
|
@@ -311,7 +330,7 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
|
|
311
330
|
|
312
331
|
def escape(string)
|
313
332
|
if string
|
314
|
-
CFURLCreateStringByAddingPercentEscapes nil, string.to_s, "[]",
|
333
|
+
CFURLCreateStringByAddingPercentEscapes nil, string.to_s, nil, "!*'();:@&=+$,/?%#[]", KCFStringEncodingUTF8
|
315
334
|
end
|
316
335
|
end
|
317
336
|
|
@@ -376,3 +395,4 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
|
|
376
395
|
end
|
377
396
|
|
378
397
|
class InvalidURLError < StandardError; end
|
398
|
+
class InvalidFileError < StandardError; end
|
data/motion/location/location.rb
CHANGED
@@ -21,6 +21,10 @@ module BubbleWrap
|
|
21
21
|
LOCATION_UNKNOWN=3
|
22
22
|
end
|
23
23
|
|
24
|
+
Constants.register KCLLocationAccuracyBestForNavigation, KCLLocationAccuracyBest,
|
25
|
+
KCLLocationAccuracyNearestTenMeters, KCLLocationAccuracyHundredMeters,
|
26
|
+
KCLLocationAccuracyKilometer, KCLLocationAccuracyThreeKilometers
|
27
|
+
|
24
28
|
module_function
|
25
29
|
# Start getting locations
|
26
30
|
# @param [Hash] options = {
|
@@ -28,7 +32,7 @@ module BubbleWrap
|
|
28
32
|
# all location changes (see Apple docs for info); default == false
|
29
33
|
# distance_filter: minimum change in distance to be updated about, in meters;
|
30
34
|
# default == uses KCLDistanceFilterNone,
|
31
|
-
# desired_accuracy: minimum accuracy for updates to arrive;
|
35
|
+
# desired_accuracy: minimum accuracy for updates to arrive;
|
32
36
|
# any of :best_for_navigation, :best, :nearest_ten_meters,
|
33
37
|
# :hundred_meters, :kilometer, or :three_kilometers; default == :best
|
34
38
|
# purpose: string to display when the system asks user for location,
|
@@ -37,7 +41,7 @@ module BubbleWrap
|
|
37
41
|
# @block for callback. takes one argument, `result`.
|
38
42
|
# - On error or cancelled, is called with a hash {error: BW::Location::Error::<Type>}
|
39
43
|
# - On success, is called with a hash {to: #<CLLocation>, from: #<CLLocation>}
|
40
|
-
#
|
44
|
+
#
|
41
45
|
# Example
|
42
46
|
# BW::Location.get(distance_filter: 10, desired_accuracy: :nearest_ten_meters) do |result|
|
43
47
|
# result[:to].class == CLLocation
|
@@ -52,6 +56,7 @@ module BubbleWrap
|
|
52
56
|
@options[:distance_filter] ||= KCLDistanceFilterNone
|
53
57
|
@options[:desired_accuracy] ||= KCLLocationAccuracyBest
|
54
58
|
@options[:retries] ||= 5
|
59
|
+
@options[:once] ||= false
|
55
60
|
@retries = 0
|
56
61
|
|
57
62
|
if not enabled?
|
@@ -59,7 +64,7 @@ module BubbleWrap
|
|
59
64
|
end
|
60
65
|
|
61
66
|
self.location_manager.distanceFilter = @options[:distance_filter]
|
62
|
-
self.location_manager.desiredAccuracy =
|
67
|
+
self.location_manager.desiredAccuracy = Constants.get("KCLLocationAccuracy", @options[:desired_accuracy])
|
63
68
|
self.location_manager.purpose = @options[:purpose] if @options[:purpose]
|
64
69
|
|
65
70
|
if @options[:significant]
|
@@ -73,6 +78,10 @@ module BubbleWrap
|
|
73
78
|
get(options.merge(significant: true), &block)
|
74
79
|
end
|
75
80
|
|
81
|
+
def get_once(options = {}, &block)
|
82
|
+
get(options.merge(once: true), &block)
|
83
|
+
end
|
84
|
+
|
76
85
|
# Stop getting locations
|
77
86
|
def stop
|
78
87
|
if @options[:significant]
|
@@ -102,7 +111,13 @@ module BubbleWrap
|
|
102
111
|
##########
|
103
112
|
# CLLocationManagerDelegate Methods
|
104
113
|
def locationManager(manager, didUpdateToLocation:newLocation, fromLocation:oldLocation)
|
105
|
-
@
|
114
|
+
if @options[:once]
|
115
|
+
@callback.call(newLocation)
|
116
|
+
@callback = proc { |result| }
|
117
|
+
stop
|
118
|
+
else
|
119
|
+
@callback.call({to: newLocation, from: oldLocation})
|
120
|
+
end
|
106
121
|
end
|
107
122
|
|
108
123
|
def locationManager(manager, didFailWithError:error)
|
@@ -134,19 +149,6 @@ module BubbleWrap
|
|
134
149
|
error(Error::PERMISSION_DENIED)
|
135
150
|
end
|
136
151
|
end
|
137
|
-
|
138
|
-
def const_int_get(base, value)
|
139
|
-
return value if value.is_a? Numeric
|
140
|
-
value = value.to_s.camelize
|
141
|
-
Kernel.const_get("#{base}#{value}")
|
142
|
-
end
|
143
|
-
|
144
|
-
def load_constants_hack
|
145
|
-
[KCLLocationAccuracyBestForNavigation, KCLLocationAccuracyBest,
|
146
|
-
KCLLocationAccuracyNearestTenMeters, KCLLocationAccuracyHundredMeters,
|
147
|
-
KCLLocationAccuracyKilometer, KCLLocationAccuracyThreeKilometers,
|
148
|
-
]
|
149
|
-
end
|
150
152
|
end
|
151
153
|
end
|
152
154
|
::Location = BubbleWrap::Location unless defined?(::Location)
|
data/motion/reactor.rb
CHANGED
@@ -37,9 +37,14 @@ module BubbleWrap
|
|
37
37
|
# Call `callback` or the passed block every `interval` seconds.
|
38
38
|
# Returns a timer signature that can be passed into
|
39
39
|
# `cancel_timer`
|
40
|
-
|
40
|
+
# Optionally supply a callback as a second argument instead of a block
|
41
|
+
# (as per EventMachine API)
|
42
|
+
# Optionally supply :common_modes => true in args to schedule the timer
|
43
|
+
# for the runloop "common modes" (NSRunLoopCommonModes) instead of
|
44
|
+
# the default runloop mode.
|
45
|
+
def add_periodic_timer(interval, *args, &blk)
|
41
46
|
@timers ||= {}
|
42
|
-
timer = PeriodicTimer.new(interval
|
47
|
+
timer = PeriodicTimer.new(interval,*args,&blk)
|
43
48
|
timer.on(:cancelled) do
|
44
49
|
@timers.delete(timer)
|
45
50
|
end
|
data/motion/reactor/eventable.rb
CHANGED
@@ -7,18 +7,28 @@ module BubbleWrap
|
|
7
7
|
# and be passed the arguments that are passed to
|
8
8
|
# `trigger`.
|
9
9
|
def on(event, &blk)
|
10
|
-
|
11
|
-
|
10
|
+
events[event].push blk
|
11
|
+
end
|
12
|
+
|
13
|
+
# When `event` is triggered, do not call the given
|
14
|
+
# block any more
|
15
|
+
def off(event, &blk)
|
16
|
+
events[event].delete_if { |b| b == blk }
|
17
|
+
blk
|
12
18
|
end
|
13
19
|
|
14
20
|
# Trigger an event
|
15
21
|
def trigger(event, *args)
|
16
|
-
|
17
|
-
@events[event].map do |event|
|
22
|
+
events[event].map do |event|
|
18
23
|
event.call(*args)
|
19
24
|
end
|
20
25
|
end
|
21
26
|
|
27
|
+
private
|
28
|
+
|
29
|
+
def events
|
30
|
+
@events ||= Hash.new { |h,k| h[k] = [] }
|
31
|
+
end
|
22
32
|
end
|
23
33
|
end
|
24
34
|
end
|
@@ -7,13 +7,19 @@ module BubbleWrap
|
|
7
7
|
attr_accessor :interval
|
8
8
|
|
9
9
|
# Create a new timer that fires after a given number of seconds
|
10
|
-
def initialize(interval,
|
10
|
+
def initialize(interval, *args, &blk)
|
11
|
+
options = args.last.is_a?(Hash) ? args.last : {}
|
12
|
+
callback = args.first.respond_to?(:call) ? args.first : blk
|
13
|
+
raise ArgumentError, "No callback or block supplied to periodic timer" unless callback
|
14
|
+
|
11
15
|
self.interval = interval
|
12
16
|
fire = proc {
|
13
|
-
|
17
|
+
callback.call
|
14
18
|
trigger(:fired)
|
15
19
|
}
|
16
|
-
@timer = NSTimer.
|
20
|
+
@timer = NSTimer.timerWithTimeInterval(interval, target: fire, selector: 'call:', userInfo: nil, repeats: true)
|
21
|
+
runloop_mode = options[:common_modes] ? NSRunLoopCommonModes : NSDefaultRunLoopMode
|
22
|
+
NSRunLoop.currentRunLoop.addTimer(@timer, forMode: runloop_mode)
|
17
23
|
end
|
18
24
|
|
19
25
|
# Cancel the timer
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module BW
|
2
|
+
module UIBarButtonItem
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def styled(type, *objects, &block)
|
6
|
+
action = block ? :call : nil
|
7
|
+
object = objects.size == 1 ? objects.first : objects
|
8
|
+
style = Constants.get("UIBarButtonItemStyle", type)
|
9
|
+
|
10
|
+
item = if object.is_a?(String)
|
11
|
+
::UIBarButtonItem.alloc.initWithTitle(object,
|
12
|
+
style:style,
|
13
|
+
target:block,
|
14
|
+
action:action
|
15
|
+
)
|
16
|
+
elsif object.is_a?(UIImage)
|
17
|
+
::UIBarButtonItem.alloc.initWithImage(object,
|
18
|
+
style:style,
|
19
|
+
target:block,
|
20
|
+
action:action
|
21
|
+
)
|
22
|
+
elsif object.is_a?(Array) && object.size == 2 && object.all? { |o| o.is_a?(UIImage) }
|
23
|
+
::UIBarButtonItem.alloc.initWithImage(object[0],
|
24
|
+
landscapeImagePhone:object[1],
|
25
|
+
style:style,
|
26
|
+
target:block,
|
27
|
+
action:action
|
28
|
+
)
|
29
|
+
else
|
30
|
+
raise ArgumentError, "invalid object - #{object.inspect}"
|
31
|
+
end
|
32
|
+
|
33
|
+
item.instance_variable_set(:@target, block)
|
34
|
+
item
|
35
|
+
end
|
36
|
+
|
37
|
+
def system(type, &block)
|
38
|
+
action = block ? :call : nil
|
39
|
+
system_item = Constants.get("UIBarButtonSystemItem", type)
|
40
|
+
|
41
|
+
item = ::UIBarButtonItem.alloc.initWithBarButtonSystemItem(system_item,
|
42
|
+
target:block,
|
43
|
+
action:action
|
44
|
+
)
|
45
|
+
item.instance_variable_set(:@target, block)
|
46
|
+
item
|
47
|
+
end
|
48
|
+
|
49
|
+
def custom(view, &block)
|
50
|
+
view.when_tapped(true, &block) if block
|
51
|
+
::UIBarButtonItem.alloc.initWithCustomView(view)
|
52
|
+
end
|
53
|
+
|
54
|
+
def build(options = {}, &block)
|
55
|
+
if options[:styled]
|
56
|
+
args = options.values_at(:title, :image, :landscape).compact
|
57
|
+
return styled(options[:styled], *args, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
return system(options[:system], &block) if options[:system]
|
61
|
+
|
62
|
+
return custom(options[:custom], &block) if options[:custom]
|
63
|
+
return custom(options[:view], &block) if options[:view]
|
64
|
+
|
65
|
+
raise ArgumentError, "invalid options - #{options.inspect}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
Constants.register(
|
70
|
+
UIBarButtonItemStylePlain,
|
71
|
+
UIBarButtonItemStyleBordered,
|
72
|
+
UIBarButtonItemStyleDone,
|
73
|
+
|
74
|
+
UIBarButtonSystemItemDone,
|
75
|
+
UIBarButtonSystemItemCancel,
|
76
|
+
UIBarButtonSystemItemEdit,
|
77
|
+
UIBarButtonSystemItemSave,
|
78
|
+
UIBarButtonSystemItemAdd,
|
79
|
+
UIBarButtonSystemItemFlexibleSpace,
|
80
|
+
UIBarButtonSystemItemFixedSpace,
|
81
|
+
UIBarButtonSystemItemCompose,
|
82
|
+
UIBarButtonSystemItemReply,
|
83
|
+
UIBarButtonSystemItemAction,
|
84
|
+
UIBarButtonSystemItemOrganize,
|
85
|
+
UIBarButtonSystemItemBookmarks,
|
86
|
+
UIBarButtonSystemItemSearch,
|
87
|
+
UIBarButtonSystemItemRefresh,
|
88
|
+
UIBarButtonSystemItemStop,
|
89
|
+
UIBarButtonSystemItemCamera,
|
90
|
+
UIBarButtonSystemItemTrash,
|
91
|
+
UIBarButtonSystemItemPlay,
|
92
|
+
UIBarButtonSystemItemPause,
|
93
|
+
UIBarButtonSystemItemRewind,
|
94
|
+
UIBarButtonSystemItemFastForward,
|
95
|
+
UIBarButtonSystemItemUndo,
|
96
|
+
UIBarButtonSystemItemRedo,
|
97
|
+
UIBarButtonSystemItemPageCurl,
|
98
|
+
)
|
99
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Stupid hack because the RubyMotion dependency detection has a bug.
|
2
|
+
module Kernel.const_get("BubbleWrap")::Constants
|
3
|
+
module_function
|
4
|
+
|
5
|
+
# Looks like RubyMotiononly adds UIKit constants
|
6
|
+
# at compile time. If you don't use these
|
7
|
+
# directly in your code, they don't get added
|
8
|
+
# to Kernel and Constants.get crashes.
|
9
|
+
# Examples
|
10
|
+
# Constants.register UIReturnKeyDone, UIReturnKeyNext
|
11
|
+
def register(*ui_constants)
|
12
|
+
# do nothing, just get the constants in the code
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param [String] base of the constant
|
16
|
+
# @param [Integer, NSArray, String, Symbol] the suffix of the constant
|
17
|
+
# when NSArray, will return the bitmask of all suffixes in the array
|
18
|
+
# @return [Integer] the constant for this base and suffix
|
19
|
+
# Examples
|
20
|
+
# get("UIReturnKey", :done) => UIReturnKeyDone == 9
|
21
|
+
# get("UIReturnKey", "done") => UIReturnKeyDone == 9
|
22
|
+
# get("UIReturnKey", 9) => 9
|
23
|
+
# get("UIImagePickerControllerSourceType", ["photo_library", "camera", "saved_photos_album"]) => 3
|
24
|
+
def get(base, *values)
|
25
|
+
value = values.size == 1 ? values.first : values.flatten
|
26
|
+
case value
|
27
|
+
when Numeric
|
28
|
+
value.to_i
|
29
|
+
when NSArray
|
30
|
+
value.reduce { |i, j|
|
31
|
+
get(base, i) | get(base, j)
|
32
|
+
}
|
33
|
+
else
|
34
|
+
value = value.to_s.camelize
|
35
|
+
Kernel.const_get("#{base}#{value}")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/resources/test.mp3
CHANGED
Binary file
|
data/samples/camera/Gemfile
CHANGED