bubble-wrap 1.4.0 → 1.5.0.rc1

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -1
  3. data/Gemfile.lock +1 -1
  4. data/README.md +22 -2
  5. data/bubble-wrap.gemspec +7 -7
  6. data/lib/bubble-wrap.rb +1 -1
  7. data/lib/bubble-wrap/core.rb +3 -3
  8. data/lib/bubble-wrap/ext.rb +0 -1
  9. data/lib/bubble-wrap/ext/motion_project_app.rb +4 -3
  10. data/lib/bubble-wrap/loader.rb +3 -3
  11. data/lib/bubble-wrap/media.rb +2 -0
  12. data/lib/bubble-wrap/requirement.rb +1 -1
  13. data/lib/bubble-wrap/version.rb +2 -2
  14. data/motion/core/device/ios/camera.rb +33 -3
  15. data/motion/core/device/ios/camera_wrapper.rb +10 -0
  16. data/motion/core/kvo.rb +18 -2
  17. data/motion/core/ns_notification_center.rb +1 -0
  18. data/motion/core/time.rb +5 -0
  19. data/motion/http/query.rb +15 -9
  20. data/motion/location/location.rb +3 -2
  21. data/motion/mail/mail.rb +2 -1
  22. data/motion/media/player.rb +10 -2
  23. data/motion/reactor.rb +2 -0
  24. data/motion/reactor/periodic_timer.rb +2 -1
  25. data/motion/shortcut.rb +8 -0
  26. data/motion/sms/sms.rb +2 -0
  27. data/motion/ui/ui_alert_view.rb +2 -0
  28. data/motion/ui/ui_bar_button_item.rb +12 -2
  29. data/motion/ui/ui_control_wrapper.rb +1 -0
  30. data/motion/ui/ui_view_wrapper.rb +5 -0
  31. data/samples/osx/Gemfile.lock +7 -3
  32. data/spec/motion/core/device/ios/camera_spec.rb +6 -0
  33. data/spec/motion/core/device/ios/camera_wrapper_spec.rb +51 -2
  34. data/spec/motion/core/kvo_spec.rb +27 -0
  35. data/spec/motion/core/ns_notification_center_spec.rb +3 -3
  36. data/spec/motion/core/time_spec.rb +13 -4
  37. data/spec/motion/core_spec.rb +0 -1
  38. data/spec/motion/http/query_spec.rb +5 -5
  39. data/spec/motion/http_spec.rb +1 -1
  40. data/spec/motion/location/location_spec.rb +2 -2
  41. data/spec/motion/mail/mail_spec.rb +1 -1
  42. data/spec/motion/media/player_spec.rb +34 -12
  43. data/spec/motion/ui/ui_bar_button_item_spec.rb +76 -0
  44. data/spec/motion/ui/ui_control_wrapper_spec.rb +38 -0
  45. data/spec/motion/ui/ui_view_wrapper_spec.rb +42 -0
  46. metadata +4 -6
  47. data/lib/bubble-wrap/ext/motion_project_config.rb +0 -34
@@ -88,7 +88,11 @@ module BubbleWrap
88
88
  if display_modal
89
89
  @presenting_controller = options[:controller]
90
90
  @presenting_controller ||= App.window.rootViewController
91
- @presenting_controller.presentMoviePlayerViewControllerAnimated(@media_player)
91
+ if Device.ios_version < "7.0"
92
+ @presenting_controller.presentMoviePlayerViewControllerAnimated(@media_player)
93
+ else
94
+ @presenting_controller.presentViewController(@media_player, animated:true, completion:nil)
95
+ end
92
96
  else
93
97
  if block.nil?
94
98
  raise Error::NilPlayerCallback, "no block callback given in #play; you need\
@@ -105,7 +109,11 @@ module BubbleWrap
105
109
  # Stops playback for a Media::Player
106
110
  def stop
107
111
  if @media_player.is_a? MPMoviePlayerViewController
108
- @presenting_controller.dismissMoviePlayerViewControllerAnimated
112
+ if Device.ios_version < "7.0"
113
+ @presenting_controller.dismissMoviePlayerViewControllerAnimated
114
+ else
115
+ @presenting_controller.dismissViewControllerAnimated(true, completion:nil)
116
+ end
109
117
  @presenting_controller = nil
110
118
  else
111
119
  @media_player.stop
data/motion/reactor.rb CHANGED
@@ -86,6 +86,7 @@ module BubbleWrap
86
86
  # Schedule a block for execution on the reactor queue.
87
87
  def schedule(*args, &blk)
88
88
  @queue ||= ::Dispatch::Queue.concurrent("#{NSBundle.mainBundle.bundleIdentifier}.reactor")
89
+ blk.weak! if blk && BubbleWrap.use_weak_callbacks?
89
90
 
90
91
  cb = proc do
91
92
  blk.call(*args)
@@ -98,6 +99,7 @@ module BubbleWrap
98
99
  # This is useful as UI updates need to be executed from the main
99
100
  # thread.
100
101
  def schedule_on_main(*args, &blk)
102
+ blk.weak! if blk && BubbleWrap.use_weak_callbacks?
101
103
  cb = proc do
102
104
  blk.call(*args)
103
105
  end
@@ -10,7 +10,8 @@ module BubbleWrap
10
10
  def initialize(interval, *args, &blk)
11
11
  callback = args.first.respond_to?(:call) ? args.first : blk
12
12
  raise ArgumentError, "No callback or block supplied to periodic timer" unless callback
13
-
13
+ callback.weak! if callback && BubbleWrap.use_weak_callbacks?
14
+
14
15
  options = args.last.is_a?(Hash) ? args.last : {}
15
16
  if options[:common_modes]
16
17
  NSLog "[DEPRECATED - Option :common_modes] a Run Loop Mode is no longer needed."
data/motion/shortcut.rb CHANGED
@@ -13,6 +13,14 @@ module BubbleWrap
13
13
  BubbleWrap::SETTINGS[:debug]
14
14
  end
15
15
 
16
+ def self.use_weak_callbacks=(val)
17
+ BubbleWrap::SETTINGS[:use_weak_callbacks] = val
18
+ end
19
+
20
+ def self.use_weak_callbacks?
21
+ BubbleWrap::SETTINGS[:use_weak_callbacks]
22
+ end
23
+
16
24
  end
17
25
 
18
26
  BW = BubbleWrap unless defined?(BW)
data/motion/sms/sms.rb CHANGED
@@ -22,6 +22,8 @@ module BubbleWrap
22
22
  def compose(options={}, &callback)
23
23
  @delegate = options[:delegate] || App.window.rootViewController
24
24
  @callback = callback
25
+ @callback.weak! if @callback && BubbleWrap.use_weak_callbacks?
26
+
25
27
  @message_controller = create_message_controller(options)
26
28
  @message_is_animated = options[:animated] == false ? false : true
27
29
  @delegate.presentModalViewController(@message_controller, animated: @message_is_animated)
@@ -28,6 +28,8 @@ module BW
28
28
  view.cancel_button_index = options[:cancel_button_index]
29
29
 
30
30
  view.instance_variable_set(:@handlers, {})
31
+ block.weak! if block && BubbleWrap.use_weak_callbacks?
32
+
31
33
  options[:on_click] ||= block
32
34
 
33
35
  callbacks.each do |callback|
@@ -2,7 +2,12 @@ module BW
2
2
  class UIBarButtonItem < ::UIBarButtonItem
3
3
  class << self
4
4
  def styled(type, *objects, &block)
5
- action = block ? :call : nil
5
+ if block.nil?
6
+ action = nil
7
+ else
8
+ block.weak! if BubbleWrap.use_weak_callbacks?
9
+ action = :call
10
+ end
6
11
  object = objects.size == 1 ? objects.first : objects
7
12
  style = Constants.get("UIBarButtonItemStyle", type)
8
13
 
@@ -34,7 +39,12 @@ module BW
34
39
  end
35
40
 
36
41
  def system(type, &block)
37
- action = block ? :call : nil
42
+ if block.nil?
43
+ action = nil
44
+ else
45
+ block.weak! if BubbleWrap.use_weak_callbacks?
46
+ action = :call
47
+ end
38
48
  system_item = Constants.get("UIBarButtonSystemItem", type)
39
49
 
40
50
  item = alloc.initWithBarButtonSystemItem(system_item, target:block, action:action)
@@ -10,6 +10,7 @@ module BubbleWrap
10
10
  end
11
11
 
12
12
  @callback[events] << block
13
+ block.weak! if BubbleWrap.use_weak_callbacks?
13
14
  addTarget(@callback[events].last, action:'call', forControlEvents: events)
14
15
  end
15
16
  end
@@ -20,6 +20,10 @@ module BubbleWrap
20
20
  add_gesture_recognizer_helper(UIPanGestureRecognizer.alloc.initWithTarget(self, action:'handle_gesture:'), enableInteraction, proc)
21
21
  end
22
22
 
23
+ def when_screen_edge_panned(enableInteraction=true, &proc)
24
+ add_gesture_recognizer_helper(UIScreenEdgePanGestureRecognizer.alloc.initWithTarget(self, action:'handle_gesture:'), enableInteraction, proc)
25
+ end
26
+
23
27
  def when_pressed(enableInteraction=true, &proc)
24
28
  add_gesture_recognizer_helper(UILongPressGestureRecognizer.alloc.initWithTarget(self, action:'handle_gesture:'), enableInteraction, proc)
25
29
  end
@@ -47,6 +51,7 @@ module BubbleWrap
47
51
  self.addGestureRecognizer(recognizer)
48
52
 
49
53
  @recognizers = {} unless @recognizers
54
+ proc.weak! if !proc.nil? && BubbleWrap.use_weak_callbacks?
50
55
  @recognizers[recognizer] = proc
51
56
 
52
57
  recognizer
@@ -1,10 +1,14 @@
1
+ PATH
2
+ remote: ../../
3
+ specs:
4
+ bubble-wrap (1.4.0)
5
+
1
6
  GEM
2
- remote: http://rubygems.org/
7
+ remote: https://rubygems.org/
3
8
  specs:
4
- bubble-wrap (1.3.0.osx)
5
9
 
6
10
  PLATFORMS
7
11
  ruby
8
12
 
9
13
  DEPENDENCIES
10
- bubble-wrap (~> 1.3.0.osx)
14
+ bubble-wrap!
@@ -93,6 +93,12 @@ describe BubbleWrap::Device::Camera do
93
93
  camera.imagePickerController(camera.instance_variable_get("@picker"), didFinishPickingMediaWithInfo: info)
94
94
  image_view.nil?.should == false
95
95
  end
96
+
97
+ it 'should set popover' do
98
+ uiview = UIView.alloc
99
+ camera = BW::Device.camera.photo_library.popover_from(uiview)
100
+ camera.instance_variable_get("@popover_in_view").should == uiview
101
+ end
96
102
  end
97
103
  end
98
104
 
@@ -1,16 +1,19 @@
1
1
  describe BubbleWrap::Device::CameraWrapper do
2
-
2
+
3
3
  before do
4
4
  BW::Device.camera.instance_variable_set(:@front, nil)
5
5
  BW::Device.camera.instance_variable_set(:@rear, nil)
6
6
  end
7
-
7
+
8
8
  describe 'on device with only front facing camera' do
9
9
  before do
10
10
  UIImagePickerController.instance_eval do
11
11
  def isCameraDeviceAvailable(c)
12
12
  c == UIImagePickerControllerCameraDeviceFront
13
13
  end
14
+ def isSourceTypeAvailable(c)
15
+ c == UIImagePickerControllerSourceTypeCamera
16
+ end
14
17
  end
15
18
  end
16
19
 
@@ -25,6 +28,12 @@ describe BubbleWrap::Device::CameraWrapper do
25
28
  BW::Device.camera.rear?.should == false
26
29
  end
27
30
  end
31
+
32
+ describe '.available?' do
33
+ it 'returns true' do
34
+ BW::Device.camera.available?.should == true
35
+ end
36
+ end
28
37
  end
29
38
 
30
39
  describe 'on device with only rear facing camera' do
@@ -33,6 +42,9 @@ describe BubbleWrap::Device::CameraWrapper do
33
42
  def isCameraDeviceAvailable(c)
34
43
  c == UIImagePickerControllerCameraDeviceRear
35
44
  end
45
+ def isSourceTypeAvailable(c)
46
+ c == UIImagePickerControllerSourceTypeCamera
47
+ end
36
48
  end
37
49
  end
38
50
 
@@ -47,5 +59,42 @@ describe BubbleWrap::Device::CameraWrapper do
47
59
  BW::Device.camera.rear?.should == true
48
60
  end
49
61
  end
62
+
63
+ describe '.available?' do
64
+ it 'returns true' do
65
+ BW::Device.camera.available?.should == true
66
+ end
67
+ end
68
+ end
69
+
70
+ describe 'on device with no physical camera' do
71
+ before do
72
+ UIImagePickerController.instance_eval do
73
+ def isCameraDeviceAvailable(c)
74
+ false
75
+ end
76
+ def isSourceTypeAvailable(c)
77
+ false
78
+ end
79
+ end
80
+ end
81
+
82
+ describe '.front?' do
83
+ it 'returns false' do
84
+ BW::Device.camera.front?.should == false
85
+ end
86
+ end
87
+
88
+ describe '.rear?' do
89
+ it 'returns false' do
90
+ BW::Device.camera.rear?.should == false
91
+ end
92
+ end
93
+
94
+ describe '.available?' do
95
+ it 'returns true' do
96
+ BW::Device.camera.available?.should == false
97
+ end
98
+ end
50
99
  end
51
100
  end
@@ -3,11 +3,13 @@ describe BubbleWrap::KVO do
3
3
  class KvoExample
4
4
  include BubbleWrap::KVO
5
5
 
6
+ attr_accessor :age
6
7
  attr_accessor :label
7
8
  attr_accessor :items
8
9
 
9
10
  def initialize
10
11
  @items = [ "Apple", "Banana", "Chickpeas" ]
12
+ @age = 1
11
13
 
12
14
  if App.osx?
13
15
  @label = NSTextField.alloc.initWithFrame [[0,0],[320, 30]]
@@ -187,6 +189,31 @@ describe BubbleWrap::KVO do
187
189
  @example.set_text "Bar"
188
190
  observed.should == false
189
191
  end
192
+
193
+ # without target
194
+
195
+ it "should observe a key path without a target" do
196
+ observed = false
197
+ @example.observe :age do |old_value, new_value|
198
+ observed = true
199
+ old_value.should == 1
200
+ new_value.should == 2
201
+ end
202
+
203
+ @example.age = 2
204
+ observed.should == true
205
+ end
206
+
207
+ it "should unobserve a key path without a target" do
208
+ observed = false
209
+ @example.observe :age do |old_value, new_value|
210
+ observed = true
211
+ end
212
+ @example.unobserve :age
213
+
214
+ @example.age = 2
215
+ observed.should == false
216
+ end
190
217
 
191
218
  end
192
219
 
@@ -14,9 +14,9 @@ describe "NSNotificationCenter" do
14
14
  end
15
15
 
16
16
  it "add observer" do
17
- notified = false
17
+ @notified = false
18
18
  @observer = BW::App.notification_center.observe(SampleNotification) do |note|
19
- notified = true
19
+ @notified = true
20
20
  note.should.is_a NSNotification
21
21
  note.object.class.should == Time
22
22
  note.userInfo.should.not.be.nil
@@ -25,7 +25,7 @@ describe "NSNotificationCenter" do
25
25
 
26
26
  lambda {
27
27
  BW::App.notification_center.post SampleNotification, Time.now, {:status => "ok"}
28
- }.should.change { notified }
28
+ }.should.change { @notified }
29
29
  end
30
30
 
31
31
  it "remove observer" do
@@ -16,13 +16,15 @@ describe "Time" do
16
16
 
17
17
  describe "parsing an iso8601 formatted time to a Time object" do
18
18
  before do
19
- @time = Time.iso8601("2012-05-31T19:41:33Z")
19
+ @time = Time.iso8601("2012-#{Time.now.month}-#{Time.now.day}T19:41:32Z")
20
20
  @time_with_timezone = Time.iso8601_with_timezone("1987-08-10T06:00:00+02:00")
21
+ @time_with_fractional_seconds = Time.iso8601_with_fractional_seconds("2012-#{Time.now.month}-#{Time.now.day}T19:41:32.123Z")
21
22
  end
22
23
 
23
24
  it "should be a time" do
24
25
  @time.instance_of?(Time).should == true
25
26
  @time_with_timezone.instance_of?(Time).should == true
27
+ @time_with_fractional_seconds.instance_of?(Time).should == true
26
28
  end
27
29
 
28
30
  # Crashes Buggy RubyMotion 1.18
@@ -30,36 +32,43 @@ describe "Time" do
30
32
  local_zone = Time.now.zone
31
33
  @time.zone.should == local_zone
32
34
  @time_with_timezone.zone == local_zone
35
+ @time_with_fractional_seconds.zone.should == local_zone
33
36
  end
34
37
 
35
38
  it "should have a valid year" do
36
39
  @time.utc.year.should == 2012
37
40
  @time_with_timezone.utc.year.should == 1987
41
+ @time_with_fractional_seconds.utc.year.should == 2012
38
42
  end
39
43
 
40
44
  it "should have a valid month" do
41
- @time.utc.month.should == 5
45
+ @time.utc.month.should == Time.now.month
42
46
  @time_with_timezone.utc.month.should == 8
47
+ @time_with_fractional_seconds.utc.month.should == Time.now.month
43
48
  end
44
49
 
45
50
  it "should have a valid day" do
46
- @time.utc.day.should == 31
51
+ @time.utc.day.should == Time.now.day
47
52
  @time_with_timezone.utc.day.should == 10
53
+ @time_with_fractional_seconds.utc.day.should == Time.now.day
48
54
  end
49
55
 
50
56
  it "should have a valid hour" do
51
57
  @time.utc.hour.should == 19
52
58
  @time_with_timezone.utc.hour.should == 4
59
+ @time_with_fractional_seconds.utc.hour.should == 19
53
60
  end
54
61
 
55
62
  it "should have a valid minute" do
56
63
  @time.utc.min.should == 41
57
64
  @time_with_timezone.utc.min.should == 0
65
+ @time_with_fractional_seconds.utc.min.should == 41
58
66
  end
59
67
 
60
68
  it "should have a valid second" do
61
- @time.utc.sec.should == 33
69
+ @time.utc.sec.should == 32
62
70
  @time_with_timezone.utc.sec.should == 0
71
+ @time_with_fractional_seconds.utc.sec.should == 32
63
72
  end
64
73
  end
65
74
 
@@ -28,7 +28,6 @@ describe 'BubbleWrap' do
28
28
  end
29
29
 
30
30
  it "creates color with rgb devided by 255 with alpha=1" do
31
- color = nil
32
31
  r,g,b,a = [(@red/255.0), (@green/255.0), (@blue/255.0), 1]
33
32
  if App.osx?
34
33
  color = NSColor.colorWithDeviceRed(r, green:g, blue:b, alpha: a)
@@ -183,7 +183,7 @@ describe BubbleWrap::HTTP::Query do
183
183
  query = BubbleWrap::HTTP::Query.new(@fake_url, :post, {files: files})
184
184
  uuid = query.instance_variable_get(:@boundary)
185
185
  real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
186
- real_payload.should.equal "--#{uuid}\r\nContent-Disposition: form-data; name=\"upload\"; filename=\"test.txt\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}--\r\n"
186
+ real_payload.should.equal "--#{uuid}\r\nContent-Disposition: attachment; name=\"upload\"; filename=\"test.txt\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}--\r\n"
187
187
  end
188
188
 
189
189
  it "processes filenames from file hashes, using the name when the filename is missing" do
@@ -193,7 +193,7 @@ describe BubbleWrap::HTTP::Query do
193
193
  query = BubbleWrap::HTTP::Query.new(@fake_url, :post, {files: files})
194
194
  uuid = query.instance_variable_get(:@boundary)
195
195
  real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
196
- real_payload.should.equal "--#{uuid}\r\nContent-Disposition: form-data; name=\"upload\"; filename=\"upload\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}--\r\n"
196
+ real_payload.should.equal "--#{uuid}\r\nContent-Disposition: attachment; name=\"upload\"; filename=\"upload\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}--\r\n"
197
197
  end
198
198
 
199
199
  it "throws an error for invalid file parameters" do
@@ -214,7 +214,7 @@ describe BubbleWrap::HTTP::Query do
214
214
  query = BubbleWrap::HTTP::Query.new( @fake_url , method, { payload: payload, files: files } )
215
215
  uuid = query.instance_variable_get(:@boundary)
216
216
  real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
217
- real_payload.should.equal "--#{uuid}\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\napple\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nmacbook\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"twitter\"; filename=\"twitter\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"site\"; filename=\"site\"\r\nContent-Type: application/octet-stream\r\n\r\nmneorr.com\r\n--#{uuid}--\r\n"
217
+ real_payload.should.equal "--#{uuid}\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\napple\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nmacbook\r\n--#{uuid}\r\nContent-Disposition: attachment; name=\"twitter\"; filename=\"twitter\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}\r\nContent-Disposition: attachment; name=\"site\"; filename=\"site\"\r\nContent-Type: application/octet-stream\r\n\r\nmneorr.com\r\n--#{uuid}--\r\n"
218
218
  end
219
219
 
220
220
  [:get, :head, :options].each do |method|
@@ -475,7 +475,7 @@ describe BubbleWrap::HTTP::Query do
475
475
 
476
476
  it "should initialize @received_data and append the received data" do
477
477
  query_received_data.should.equal nil
478
- data = NSData.dataWithBytesNoCopy(Pointer.new(:char, 'abc'), length:24, freeWhenDone: false)
478
+ data = NSData.dataWithBytes(Pointer.new(:char, 'abc'), length:24)
479
479
 
480
480
  @query.connection(nil, didReceiveData:nil)
481
481
  query_received_data.should.not.equal nil
@@ -555,7 +555,7 @@ describe BubbleWrap::HTTP::Query do
555
555
  end
556
556
 
557
557
  it "should set response_body to @received data if not nil" do
558
- data = NSData.dataWithBytesNoCopy(Pointer.new(:char, 'abc'), length:24, freeWhenDone: false)
558
+ data = NSData.dataWithBytes(Pointer.new(:char, 'abc'), length:24)
559
559
  headers = { foo: 'bar' }
560
560
  status_code = 234
561
561
  response = FakeURLResponse.new(status_code, headers, 65456)