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.
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
- form_data.appendData(s.dataUsingEncoding NSUTF8StringEncoding)
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
- file_data = NSMutableData.new
295
+ file = parse_file(key, value)
278
296
  s = "--#{@boundary}\r\n"
279
- s += "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{key}\"\r\n"
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(value)
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, "[]", ";=&,", KCFStringEncodingUTF8
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
@@ -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 = const_int_get("KCLLocationAccuracy", @options[:desired_accuracy])
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
- @callback.call({to: newLocation, from: oldLocation})
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
- def add_periodic_timer(interval, callback=nil, &blk)
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,callback,&blk)
47
+ timer = PeriodicTimer.new(interval,*args,&blk)
43
48
  timer.on(:cancelled) do
44
49
  @timers.delete(timer)
45
50
  end
@@ -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
- @events ||= Hash.new { |h,k| h[k] = [] }
11
- @events[event].push blk
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
- @events ||= Hash.new { |h,k| h[k] = [] }
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, callback=nil, &blk)
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
- (callback || blk).call
17
+ callback.call
14
18
  trigger(:fired)
15
19
  }
16
- @timer = NSTimer.scheduledTimerWithTimeInterval(interval,target: fire, selector: 'call:', userInfo: nil, repeats: true)
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
@@ -1,3 +1,3 @@
1
- source :rubygems
1
+ source "https://rubygems.org"
2
2
 
3
3
  gem 'bubble-wrap', '~> 1.1.0'