bubble-wrap 1.1.4 → 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.1.4...master)
4
4
 
5
- ## 1.1.4 (Unreleased)
5
+ ## 1.1.4
6
6
 
7
7
  [Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.1.3...v1.1.4)
8
8
 
data/README.md CHANGED
@@ -192,6 +192,8 @@ Examples:
192
192
  # :portrait
193
193
  > Device.simulator?
194
194
  # true
195
+ > Device.ios_version
196
+ # "6.0"
195
197
  > Device.retina?
196
198
  # false
197
199
  > Device.screen.width
@@ -372,7 +374,7 @@ BW::Media.play_modal("http://www.hrupin.com/wp-content/uploads/mp3/testsong_20_s
372
374
  Extra methods on `UIView` for working with gesture recognizers. A gesture recognizer can be added using a normal Ruby block, like so:
373
375
 
374
376
  ```ruby
375
- view.whenTapped do
377
+ view.when_tapped do
376
378
  UIView.animateWithDuration(1,
377
379
  animations:lambda {
378
380
  # animate
@@ -381,7 +383,7 @@ Extra methods on `UIView` for working with gesture recognizers. A gesture recogn
381
383
  end
382
384
  ```
383
385
 
384
- There are similar methods for pinched, rotated, swiped, panned, and pressed (for long presses). All of the methods return the actual recognizer object, so it is possible to set the delegate if more fine-grained control is needed.
386
+ There are similar methods for `pinched`, `rotated`, `swiped`, `panned`, and `pressed` (for long presses). All of the methods return the actual recognizer object, so it is possible to set the delegate if more fine-grained control is needed.
385
387
 
386
388
  ### UIViewController
387
389
 
@@ -1,5 +1,5 @@
1
1
  module BubbleWrap
2
- VERSION = '1.1.4' unless defined?(BubbleWrap::VERSION)
2
+ VERSION = '1.1.5' unless defined?(BubbleWrap::VERSION)
3
3
  MIN_MOTION_VERSION = '1.24'
4
4
 
5
5
  module_function
@@ -13,6 +13,12 @@ module BubbleWrap
13
13
  def ipad?(idiom=UIDevice.currentDevice.userInterfaceIdiom)
14
14
  idiom == UIUserInterfaceIdiomPad
15
15
  end
16
+
17
+ # Verifies that the device having a long screen (4 inch iPhone/iPod)
18
+ # @return [TrueClass, FalseClass] true will be returned if the device is an iPhone/iPod with 4 inche screen, false otherwise.
19
+ def long_screen?(idiom=UIDevice.currentDevice.userInterfaceIdiom, screen_height=UIScreen.mainScreen.bounds.size.height)
20
+ iphone?(idiom) && screen_height == 568.0
21
+ end
16
22
 
17
23
  # Use this to make a DSL-style call for picking images
18
24
  # @example Device.camera.front
@@ -39,6 +45,12 @@ module BubbleWrap
39
45
  @simulator_state ||= !(UIDevice.currentDevice.model =~ /simulator/i).nil?
40
46
  end
41
47
 
48
+ # Returns the IOS SDK version currently running (i.e. "5.1" or "6.0" etc)
49
+ # @return [String] the IOS SDK version currently running
50
+ def ios_version
51
+ UIDevice.currentDevice.systemVersion
52
+ end
53
+
42
54
  # Shameless shorthand for accessing BubbleWrap::Screen
43
55
  def screen
44
56
  BubbleWrap::Device::Screen
@@ -21,17 +21,17 @@ module BubbleWrap
21
21
 
22
22
  def self.front
23
23
  return nil if not UIImagePickerController.isCameraDeviceAvailable(UIImagePickerControllerCameraDeviceFront)
24
- Camera.new(:front).retain
24
+ @front ||= Camera.new(:front)
25
25
  end
26
26
 
27
27
  def self.rear
28
28
  return nil if not UIImagePickerController.isCameraDeviceAvailable(UIImagePickerControllerCameraDeviceRear)
29
- Camera.new(:rear).retain
29
+ @rear ||= Camera.new(:rear)
30
30
  end
31
31
 
32
32
  # For uploading photos from the library.
33
33
  def self.any
34
- Camera.new.retain
34
+ @any ||= Camera.new
35
35
  end
36
36
 
37
37
  def initialize(location = :none)
@@ -117,6 +117,7 @@ module BubbleWrap
117
117
  self.picker.cameraDevice = camera_device
118
118
  end
119
119
 
120
+ presenting_controller ||= App.window.rootViewController.presentedViewController # May be nil, but handles use case of container views
120
121
  presenting_controller ||= App.window.rootViewController
121
122
  presenting_controller.presentViewController(self.picker, animated:@options[:animated], completion: lambda {})
122
123
  end
@@ -217,4 +218,4 @@ module BubbleWrap
217
218
  end
218
219
  end
219
220
  end
220
- ::Camera = BubbleWrap::Device::Camera unless defined?(::Camera)
221
+ ::Camera = BubbleWrap::Device::Camera unless defined?(::Camera)
@@ -7,7 +7,7 @@ module BubbleWrap
7
7
  # The front-facing camera used to capture media
8
8
  # @return [Device::Camera, NilClass] a Camera will be returned if there is a front camera, nil otherwise
9
9
  def front
10
- BubbleWrap::Device::Camera.front
10
+ @front ||= BubbleWrap::Device::Camera.front
11
11
  end
12
12
 
13
13
  # Verifies that the device running has a front facing camera.
@@ -19,7 +19,7 @@ module BubbleWrap
19
19
  # The rear-facing camera used to capture media
20
20
  # @return [Device::Camera, NilClass] a Camera will be returned if there is a rear camera, nil otherwise
21
21
  def rear
22
- BubbleWrap::Device::Camera.rear
22
+ @rear ||= BubbleWrap::Device::Camera.rear
23
23
  end
24
24
 
25
25
  # Verifies that the device running has a rear facing camera.
@@ -32,7 +32,7 @@ module BubbleWrap
32
32
  # See Device::Camera docs for more source type options.
33
33
  # @return [Device::Camera] a Camera will always be returned.
34
34
  def any
35
- BubbleWrap::Device::Camera.any
35
+ @any ||= BubbleWrap::Device::Camera.any
36
36
  end
37
37
 
38
38
  # Should always return true, since picking images from *some* source is always possible
@@ -16,7 +16,7 @@ module BubbleWrap
16
16
 
17
17
  # Figure out the current physical orientation of the device
18
18
  # @return [:portrait, :portrait_upside_down, :landscape_left, :landscape_right, :face_up, :face_down, :unknown]
19
- def orientation(device_orientation=UIDevice.currentDevice.orientation)
19
+ def orientation(device_orientation=UIDevice.currentDevice.orientation, fallback=true)
20
20
  case device_orientation
21
21
  when UIDeviceOrientationPortrait then :portrait
22
22
  when UIDeviceOrientationPortraitUpsideDown then :portrait_upside_down
@@ -25,7 +25,13 @@ module BubbleWrap
25
25
  when UIDeviceOrientationFaceUp then :face_up
26
26
  when UIDeviceOrientationFaceDown then :face_down
27
27
  else
28
- :unknown
28
+ # In some cases, the accelerometer can't get an accurate read of orientation so we fall back on the orientation of
29
+ # the status bar.
30
+ if fallback && (device_orientation != UIApplication.sharedApplication.statusBarOrientation)
31
+ orientation(UIApplication.sharedApplication.statusBarOrientation)
32
+ else
33
+ :unknown
34
+ end
29
35
  end
30
36
  end
31
37
 
data/motion/core/json.rb CHANGED
@@ -15,7 +15,7 @@ module BubbleWrap
15
15
  def self.parse(str_data, &block)
16
16
  return nil unless str_data
17
17
  data = str_data.respond_to?(:to_data) ? str_data.to_data : str_data
18
- opts = NSJSONReadingMutableContainers & NSJSONReadingMutableLeaves & NSJSONReadingAllowFragments
18
+ opts = NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves | NSJSONReadingAllowFragments
19
19
  error = Pointer.new(:id)
20
20
  obj = NSJSONSerialization.JSONObjectWithData(data, options:opts, error:error)
21
21
  raise ParserError, error[0].description if error[0]
data/motion/http.rb CHANGED
@@ -100,6 +100,7 @@ module BubbleWrap
100
100
  @headers = escape_line_feeds(options.delete :headers)
101
101
  @format = options.delete(:format)
102
102
  @cache_policy = options.delete(:cache_policy) || NSURLRequestUseProtocolCachePolicy
103
+ @credential_persistence = options.delete(:credential_persistence) || NSURLCredentialPersistenceForSession
103
104
  @options = options
104
105
  @response = HTTP::Response.new
105
106
 
@@ -175,9 +176,14 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
175
176
 
176
177
  def connection(connection, didReceiveAuthenticationChallenge:challenge)
177
178
  if (challenge.previousFailureCount == 0)
178
- new_credential = NSURLCredential.credentialWithUser(credentials[:username], password:credentials[:password], persistence:NSURLCredentialPersistenceForSession)
179
- challenge.sender.useCredential(new_credential, forAuthenticationChallenge:challenge)
180
- log "auth challenged, answered with credentials: #{credentials.inspect}"
179
+ if credentials[:username].to_s.empty? && credentials[:password].to_s.empty?
180
+ challenge.sender.continueWithoutCredentialForAuthenticationChallenge(challenge)
181
+ log 'Continue without credentials to get 401 status in response'
182
+ else
183
+ new_credential = NSURLCredential.credentialWithUser(credentials[:username], password:credentials[:password], persistence:@credential_persistence)
184
+ challenge.sender.useCredential(new_credential, forAuthenticationChallenge:challenge)
185
+ log "auth challenged, answered with credentials: #{credentials.inspect}"
186
+ end
181
187
  else
182
188
  challenge.sender.cancelAuthenticationChallenge(challenge)
183
189
  log 'Auth Failed :('
@@ -286,11 +292,12 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
286
292
  end
287
293
 
288
294
  def create_url(url_string)
295
+ url_string = url_string.stringByAddingPercentEscapesUsingEncoding NSUTF8StringEncoding
289
296
  if (@method == "GET" || @method == "HEAD") && @payload
290
297
  convert_payload_to_url if @payload.is_a?(Hash)
291
298
  url_string += "?#{@payload}"
292
299
  end
293
- url = NSURL.URLWithString(url_string.stringByAddingPercentEscapesUsingEncoding NSUTF8StringEncoding)
300
+ url = NSURL.URLWithString(url_string)
294
301
 
295
302
  validate_url(url)
296
303
  url
@@ -302,9 +309,15 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
302
309
  end
303
310
  end
304
311
 
312
+ def escape(string)
313
+ if string
314
+ CFURLCreateStringByAddingPercentEscapes nil, string.to_s, "[]", ";=&,", KCFStringEncodingUTF8
315
+ end
316
+ end
317
+
305
318
  def convert_payload_to_url
306
319
  params_array = process_payload_hash(@payload)
307
- params_array.map! { |key, value| "#{key}=#{value}" }
320
+ params_array.map! { |key, value| "#{escape key}=#{escape value}" }
308
321
  @payload = params_array.join("&")
309
322
  end
310
323
 
data/motion/reactor.rb CHANGED
@@ -50,7 +50,7 @@ module BubbleWrap
50
50
  # Defer is for integrating blocking operations into the reactor's control
51
51
  # flow.
52
52
  # Call defer with one or two blocks, the second block is optional.
53
- # operator = proc do
53
+ # operation = proc do
54
54
  # # perform a long running operation here
55
55
  # "result"
56
56
  # end
@@ -25,40 +25,18 @@ class UIView
25
25
  def when_pressed(enableInteraction=true, &proc)
26
26
  add_gesture_recognizer_helper(UILongPressGestureRecognizer.alloc.initWithTarget(self, action:'handle_gesture:'), enableInteraction, proc)
27
27
  end
28
-
29
-
30
- def whenTapped(enableInteraction=true, &proc)
31
- NSLog "[DEPRECATED - whenTapped] please use when_tapped instead."
32
- when_tapped(enableInteraction, &proc)
33
- end
34
-
35
- def whenPinched(enableInteraction=true, &proc)
36
- NSLog "[DEPRECATED - whenPinched] please use when_pinched instead."
37
- when_pinched(enableInteraction, &proc)
38
- end
39
-
40
- def whenRotated(enableInteraction=true, &proc)
41
- NSLog "[DEPRECATED - whenRotated] please use when_rotated instead."
42
- when_rotated(enableInteraction, &proc)
28
+
29
+ def self.deprecated_methods
30
+ %w(whenTapped whenPinched whenRotated whenSwiped whenPanned whenPressed)
43
31
  end
44
32
 
45
- def whenSwiped(enableInteraction=true, &proc)
46
- NSLog "[DEPRECATED - whenSwiped] please use when_swiped instead."
47
- when_swiped(enableInteraction, &proc)
33
+ deprecated_methods.each do |method|
34
+ define_method(method) do |enableInteraction = true, &proc|
35
+ NSLog "[DEPRECATED - #{method}] please use #{method.underscore} instead."
36
+ send(method.underscore, enableInteraction, &proc)
37
+ end
48
38
  end
49
39
 
50
- def whenPanned(enableInteraction=true, &proc)
51
- NSLog "[DEPRECATED - whenPanned] please use when_panned instead."
52
- when_panned(enableInteraction, &proc)
53
- end
54
-
55
- def whenPressed(enableInteraction=true, &proc)
56
- NSLog "[DEPRECATED - whenPressed] please use when_pressed instead."
57
- when_pressed(enableInteraction, &proc)
58
- end
59
-
60
-
61
-
62
40
  private
63
41
 
64
42
  def handle_gesture(recognizer)
@@ -182,12 +182,18 @@ describe BubbleWrap::App do
182
182
  end
183
183
  end
184
184
 
185
- describe '.app' do
185
+ describe '.shared' do
186
186
  it 'returns UIApplication.sharedApplication' do
187
187
  App.shared.should == UIApplication.sharedApplication
188
188
  end
189
189
  end
190
190
 
191
+ describe '.window' do
192
+ it 'returns UIApplication.sharedApplication.keyWindow' do
193
+ App.window.should == UIApplication.sharedApplication.keyWindow
194
+ end
195
+ end
196
+
191
197
  describe '.run_after' do
192
198
  class DelayedRunAfterTest; attr_accessor :test_value end
193
199
 
@@ -1,4 +1,10 @@
1
1
  describe BubbleWrap::Device::CameraWrapper do
2
+
3
+ before do
4
+ BW::Device.camera.instance_variable_set(:@front, nil)
5
+ BW::Device.camera.instance_variable_set(:@rear, nil)
6
+ end
7
+
2
8
  describe 'on device with only front facing camera' do
3
9
  before do
4
10
  UIImagePickerController.instance_eval do
@@ -85,14 +85,20 @@ describe BubbleWrap::Device::Screen do
85
85
  end
86
86
 
87
87
  describe 'unknown' do
88
- it 'returns :unknown' do
89
- BW::Device::Screen.orientation(UIDeviceOrientationUnknown).should == :unknown
88
+ it 'returns :unknown if fallback is false' do
89
+ BW::Device::Screen.orientation(UIDeviceOrientationUnknown, false).should == :unknown
90
+ end
91
+ it 'returns Status bar orientation if fallback not specified' do
92
+ BW::Device::Screen.orientation(UIDeviceOrientationUnknown).should == BW::Device::Screen.orientation(UIApplication.sharedApplication.statusBarOrientation)
90
93
  end
91
94
  end
92
95
 
93
96
  describe 'any other input' do
94
- it 'returns :unknown' do
95
- BW::Device::Screen.orientation('twiggy twiggy twiggy').should == :unknown
97
+ it 'returns :unknown if fallback is false' do
98
+ BW::Device::Screen.orientation('twiggy twiggy twiggy', false).should == :unknown
99
+ end
100
+ it 'returns Status bar orientation if fallback not specified' do
101
+ BW::Device::Screen.orientation('twiggy twiggy twiggy').should == BW::Device::Screen.orientation(UIApplication.sharedApplication.statusBarOrientation)
96
102
  end
97
103
  end
98
104
  end
@@ -16,6 +16,16 @@ describe BubbleWrap::Device do
16
16
  BW::Device.ipad?(@idiom).should == false
17
17
  end
18
18
  end
19
+
20
+ describe '.long_screen?' do
21
+ it 'returns true if screen is wide' do
22
+ BW::Device.long_screen?(@idiom, 568.0).should == true
23
+ end
24
+
25
+ it 'returns false if screen is not wide' do
26
+ BW::Device.long_screen?(@idiom, 480.0).should == false
27
+ end
28
+ end
19
29
  end
20
30
 
21
31
  describe 'on iPad' do
@@ -34,6 +44,12 @@ describe BubbleWrap::Device do
34
44
  BW::Device.ipad?(@idiom).should == true
35
45
  end
36
46
  end
47
+
48
+ describe '.long_screen?' do
49
+ it 'always not a widescreen' do
50
+ BW::Device.long_screen?(@idiom, 1024.0).should == false
51
+ end
52
+ end
37
53
  end
38
54
 
39
55
  describe '.simulator?' do
@@ -42,6 +58,13 @@ describe BubbleWrap::Device do
42
58
  end
43
59
  end
44
60
 
61
+ describe '.ios_version' do
62
+ it 'returns true' do
63
+ # exact value depends on system where specs run. 4.0 seems like a safe guess
64
+ BW::Device.ios_version.should > '4.0'
65
+ end
66
+ end
67
+
45
68
  describe '.screen' do
46
69
  it 'return BubbleWrap::Screen' do
47
70
  BW::Device.screen.should == BW::Device::Screen
@@ -36,6 +36,10 @@ EOS
36
36
  Proc.new { BW::JSON.parse(nil) }.should.not.raise Exception
37
37
  end
38
38
 
39
+ it "returns a mutable object" do
40
+ Proc.new { @parsed[:blah] = 123 }.should.not.raise Exception
41
+ end
42
+
39
43
  it "should convert a top object into a Ruby hash" do
40
44
  obj = @parsed
41
45
  obj.class.should == Hash
@@ -103,6 +103,7 @@ describe "HTTP" do
103
103
 
104
104
  before do
105
105
  @credentials = { username: 'mneorr', password: '123456xx!@crazy' }
106
+ @credential_persistence = 0
106
107
  @payload = {
107
108
  user: { name: 'marin', surname: 'usalj' },
108
109
  twitter: '@mneorr',
@@ -124,6 +125,7 @@ describe "HTTP" do
124
125
  files: @files,
125
126
  payload: @payload,
126
127
  credentials: @credentials,
128
+ credential_persistence: @credential_persistence,
127
129
  headers: @headers,
128
130
  cache_policy: @cache_policy,
129
131
  leftover_option: @leftover_option,
@@ -316,6 +318,14 @@ describe "HTTP" do
316
318
  new_query.instance_variable_get(:@cache_policy).should.equal NSURLRequestUseProtocolCachePolicy
317
319
  end
318
320
 
321
+ it "should delete :credential_persistence or set NSURLCredentialPersistenceForSession" do
322
+ @query.instance_variable_get(:@credential_persistence).should.equal @credential_persistence
323
+ @options.should.not.has_key? :credential_persistence
324
+
325
+ new_query = BubbleWrap::HTTP::Query.new( @localhost_url, :get, {})
326
+ new_query.instance_variable_get(:@credential_persistence).should.equal NSURLCredentialPersistenceForSession
327
+ end
328
+
319
329
  it "should set the rest of options{} to ivar @options" do
320
330
  @query.options.size.should.equal 1
321
331
  @query.options.values[0].should.equal @leftover_option
@@ -614,14 +624,36 @@ describe "HTTP" do
614
624
  @challenge.sender.credential.password.should.equal @credentials[:password]
615
625
  end
616
626
 
617
- it "always uses NSURLCredentialPersistenceForSession" do
618
- @challenge.sender.credential.persistence.should.equal NSURLCredentialPersistenceForSession
627
+ it "should use Credential Persistence set in options" do
628
+ @challenge.sender.credential.persistence.should.equal @credential_persistence
629
+ end
630
+
631
+ it 'should continue without credentials when no credentials provided' do
632
+ @options.delete :credentials
633
+ @query = BubbleWrap::HTTP::Query.new( @localhost_url , :get, @options )
634
+ @query.connection(nil, didReceiveAuthenticationChallenge:@challenge)
635
+ @challenge.sender.continue_without_credential.should.equal true
636
+ end
637
+
638
+ end
639
+
640
+ describe "properly format payload to url get query string" do
641
+
642
+ before do
643
+ @payload = {"we love" => '#==Rock&Roll==#', "radio" => "Ga Ga", "qual" => 3.0, "incr" => -1}
644
+ @url_string = 'http://fake.url/method'
645
+ @get_query = BubbleWrap::HTTP::Query.new( @url_string, :get, :payload => @payload)
646
+ @escaped_url = "http://fake.url/method?we%20love=%23%3D%3DRock%26Roll%3D%3D%23&radio=Ga%20Ga&qual=3.0&incr=-1"
647
+ end
648
+
649
+ it "should escape \#=& characters only in keys and values" do
650
+ @get_query.instance_variable_get(:@url).description.should.equal @escaped_url
619
651
  end
620
652
 
621
653
  end
622
654
 
623
655
  class FakeSender
624
- attr_reader :challenge, :credential, :was_cancelled
656
+ attr_reader :challenge, :credential, :was_cancelled, :continue_without_credential
625
657
  def cancelAuthenticationChallenge(challenge)
626
658
  @was_cancelled = true
627
659
  end
@@ -629,6 +661,9 @@ describe "HTTP" do
629
661
  @challenge = challenge
630
662
  @credential = credential
631
663
  end
664
+ def continueWithoutCredentialForAuthenticationChallenge(challenge)
665
+ @continue_without_credential = true
666
+ end
632
667
  end
633
668
 
634
669
  class FakeChallenge
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bubble-wrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.1.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2012-09-26 00:00:00.000000000 Z
18
+ date: 2013-01-22 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: mocha
@@ -289,21 +289,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
289
289
  - - ! '>='
290
290
  - !ruby/object:Gem::Version
291
291
  version: '0'
292
- segments:
293
- - 0
294
- hash: -27678325849561073
295
292
  required_rubygems_version: !ruby/object:Gem::Requirement
296
293
  none: false
297
294
  requirements:
298
295
  - - ! '>='
299
296
  - !ruby/object:Gem::Version
300
297
  version: '0'
301
- segments:
302
- - 0
303
- hash: -27678325849561073
304
298
  requirements: []
305
299
  rubyforge_project:
306
- rubygems_version: 1.8.24
300
+ rubygems_version: 1.8.23
307
301
  signing_key:
308
302
  specification_version: 3
309
303
  summary: RubyMotion wrappers and helpers (Ruby for iOS) - Making Cocoa APIs more Ruby
@@ -336,3 +330,4 @@ test_files:
336
330
  - spec/motion/reactor/eventable_spec.rb
337
331
  - spec/motion/reactor_spec.rb
338
332
  - spec/motion/rss_parser_spec.rb
333
+ has_rdoc: