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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f49e903b8cbae3bf9a475a04c9fa209aa944ab60
4
- data.tar.gz: aa486c325db87d7d54eb5647f8acce0e28ef6e48
3
+ metadata.gz: 6fe8341489f7d867922c2a8c271efa986f434521
4
+ data.tar.gz: eb3ed530d9b58a39525049fe03286e83f4add2cf
5
5
  SHA512:
6
- metadata.gz: 83bf22da6648b81fbc4b7717445ea63154ad10fad278767958fb074ec41c2fce7d792022d87ff629925940e5d6f20cea2791e97614155963e071aa8580f82867
7
- data.tar.gz: 1e5d77f5ec252c58a78fe372eddb3a0f7468d13b36344dd4cb12cf6162d3fdd70ba1db5d9911f709b4865d978ca698b040a9e0dba27a64e930aa99e054e84647
6
+ metadata.gz: fadcc0db6e1ca10ba457ff651cac9b66315834dce161d33e026ebadafc78748da0fd481f59c78007754bd9c7f0cb45463b784160ec49bb354d202b7cab7f8d0a
7
+ data.tar.gz: 3ff86b7387349720e3aec8b48dba3efca6e7d1a2c988023634cfa693569a158124a1e1f41d50abe90068211b86971c0467c98cb207120077d10455d72dffa858
data/.travis.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  language: objective-c
2
2
  before_install:
3
3
  - (ruby --version)
4
- before_script: sudo chown -R travis ~/Library/RubyMotion
4
+ - mkdir -p ~/Library/RubyMotion/build
5
+ - sudo motion update
5
6
  script: ./travis.sh
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bubble-wrap (1.4.0)
4
+ bubble-wrap (1.5.0.rc1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -23,10 +23,10 @@ gem install bubble-wrap
23
23
  require 'bubble-wrap'
24
24
  ```
25
25
 
26
- If you are requiring bubble-wrap for RubyMotion 2.0 (iOS or OS X), use Bundler and specify version greater than 1.3.0:
26
+ If you using Bundler:
27
27
 
28
28
  ```ruby
29
- gem "bubble-wrap", "~> 1.3.0"
29
+ gem "bubble-wrap", "~> 1.4.0"
30
30
  ```
31
31
 
32
32
  BubbleWrap is split into multiple modules so that you can easily choose which parts
@@ -479,6 +479,12 @@ button.when(UIControlEventTouchUpInside) do
479
479
  end
480
480
  ```
481
481
 
482
+ Set the use_weak_callbacks flag so the blocks do not retain a strong reference to self:
483
+
484
+ ```ruby
485
+ BubbleWrap.use_weak_callbacks = true
486
+ ```
487
+
482
488
  ### UIBarButtonItem
483
489
 
484
490
  `BW::UIBarButtonItem` is a subclass of `UIBarButtonItem` with an natural Ruby syntax.
@@ -626,6 +632,20 @@ BW::HTTP.post("http://foo.bar.com/", {payload: data}) do |response|
626
632
  end
627
633
  ```
628
634
 
635
+ To upload files to a server, provide a `files:` hash:
636
+
637
+ ```ruby
638
+ data = {token: "some-api-token"}
639
+ avatar_data = UIImagePNGRepresentation(UIImage.imageNamed("some-image"))
640
+ avatar = { data: avatar_data, filename: "some-image.png", content_type: "image/png" }
641
+
642
+ BW::HTTP.post("http://foo.bar.com/", {payload: data}, files: { avatar: avatar }) do |response|
643
+ if response.ok?
644
+ # files are uploaded
645
+ end
646
+ end
647
+ ```
648
+
629
649
  A `:download_progress` option can also be passed. The expected object
630
650
  would be a Proc that takes two arguments: a float representing the
631
651
  amount of data currently received and another float representing the
data/bubble-wrap.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  require File.expand_path('../lib/bubble-wrap/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
- gem.authors = ["Matt Aimonetti", "Francis Chong", "James Harton", "Clay Allsopp", "Dylan Markow", "Jan Weinkauff", "Marin Usalj"]
6
- gem.email = ["mattaimonetti@gmail.com", "francis@ignition.hk", "james@sociable.co.nz", "clay.allsopp@gmail.com", "dylan@dylanmarkow.com", "jan@dreimannzelt.de", "mneorr@gmail.com"]
7
- gem.description = "RubyMotion wrappers and helpers (Ruby for iOS) - Making Cocoa APIs more Ruby like, one API at a time. Fork away and send your pull request."
8
- gem.summary = "RubyMotion wrappers and helpers (Ruby for iOS) - Making Cocoa APIs more Ruby like, one API at a time. Fork away and send your pull request."
9
- gem.homepage = "http://bubblewrap.io/"
5
+ gem.authors = ['Matt Aimonetti', 'Francis Chong', 'James Harton', 'Clay Allsopp', 'Dylan Markow', 'Jan Weinkauff', 'Marin Usalj']
6
+ gem.email = ['mattaimonetti@gmail.com', 'francis@ignition.hk', 'james@sociable.co.nz', 'clay.allsopp@gmail.com', 'dylan@dylanmarkow.com', 'jan@dreimannzelt.de', 'mneorr@gmail.com']
7
+ gem.description = 'RubyMotion wrappers and helpers (Ruby for iOS) - Making Cocoa APIs more Ruby like, one API at a time. Fork away and send your pull request.'
8
+ gem.summary = 'RubyMotion wrappers and helpers (Ruby for iOS) - Making Cocoa APIs more Ruby like, one API at a time. Fork away and send your pull request.'
9
+ gem.homepage = 'http://bubblewrap.io/'
10
10
 
11
11
  gem.files = `git ls-files`.split($\)
12
12
  gem.test_files = gem.files.grep(%r{^(test|spec|lib_spec|features)/})
13
- gem.name = "bubble-wrap"
14
- gem.require_paths = ["lib"]
13
+ gem.name = 'bubble-wrap'
14
+ gem.require_paths = ['lib']
15
15
  gem.version = BubbleWrap::VERSION
16
16
 
17
17
  gem.extra_rdoc_files = gem.files.grep(%r{motion})
data/lib/bubble-wrap.rb CHANGED
@@ -1,3 +1,3 @@
1
- require "bubble-wrap/version" unless defined?(BubbleWrap::VERSION)
1
+ require 'bubble-wrap/version' unless defined?(BubbleWrap::VERSION)
2
2
  require File.expand_path('../bubble-wrap/core', __FILE__)
3
3
  require File.expand_path('../bubble-wrap/http', __FILE__)
@@ -9,12 +9,12 @@ BubbleWrap.require('motion/core/device/*.rb')
9
9
  BubbleWrap.require_ios do
10
10
  BubbleWrap.require('motion/core/ios/**/*.rb')
11
11
  BubbleWrap.require('motion/core/device/ios/**/*.rb')
12
+
13
+ require 'bubble-wrap/camera'
14
+ require 'bubble-wrap/ui'
12
15
  end
13
16
 
14
17
  BubbleWrap.require_osx do
15
18
  BubbleWrap.require('motion/core/osx/**/*.rb')
16
19
  BubbleWrap.require('motion/core/device/osx/**/*.rb')
17
20
  end
18
-
19
- require 'bubble-wrap/camera'
20
- require 'bubble-wrap/ui'
@@ -1,2 +1 @@
1
- require 'bubble-wrap/ext/motion_project_config'
2
1
  require 'bubble-wrap/ext/motion_project_app'
@@ -4,14 +4,15 @@ module BubbleWrap
4
4
 
5
5
  def self.extended(base)
6
6
  base.instance_eval do
7
- def setup_with_bubblewrap(&block)
7
+ def setup_with_bubblewrap(*args, &block)
8
8
  bw_config = proc do |app|
9
9
  app.files = ::BubbleWrap::Requirement.files(app.files)
10
10
  app.files_dependencies ::BubbleWrap::Requirement.files_dependencies
11
11
  app.frameworks = ::BubbleWrap::Requirement.frameworks(app.frameworks)
12
12
  block.call(app) unless block.nil?
13
13
  end
14
- config.setup_blocks << bw_config
14
+
15
+ setup_without_bubblewrap *args, &bw_config
15
16
  end
16
17
  alias :setup_without_bubblewrap :setup
17
18
  alias :setup :setup_with_bubblewrap
@@ -30,4 +31,4 @@ end
30
31
 
31
32
  Motion::Project::App.extend(BubbleWrap::Ext::BuildTask)
32
33
 
33
- Motion::Project::App.extend(BubbleWrap::Ext::Platforms)
34
+ Motion::Project::App.extend(BubbleWrap::Ext::Platforms)
@@ -1,5 +1,5 @@
1
1
  unless defined?(Motion::Project::Config)
2
- raise "This file must be required within a RubyMotion project Rakefile."
2
+ raise 'This file must be required within a RubyMotion project Rakefile.'
3
3
  end
4
4
 
5
5
  unless defined?(BubbleWrap::LOADER_PRESENT)
@@ -13,7 +13,7 @@ unless defined?(BubbleWrap::LOADER_PRESENT)
13
13
 
14
14
  module BubbleWrap
15
15
 
16
- LOADER_PRESENT=true
16
+ LOADER_PRESENT = true
17
17
  module_function
18
18
 
19
19
  def root
@@ -44,5 +44,5 @@ unless defined?(BubbleWrap::LOADER_PRESENT)
44
44
  BW = BubbleWrap unless defined?(BW)
45
45
 
46
46
  BW.require 'motion/shortcut.rb'
47
-
47
+
48
48
  end
@@ -2,6 +2,8 @@ require 'bubble-wrap/loader'
2
2
 
3
3
  BubbleWrap.require_ios("media") do
4
4
  BubbleWrap.require('motion/core/app.rb')
5
+ BubbleWrap.require('motion/core/ios/app.rb')
6
+ BubbleWrap.require('motion/core/ios/device.rb')
5
7
  BubbleWrap.require('motion/core/string.rb')
6
8
  BubbleWrap.require('motion/core/ns_notification_center.rb')
7
9
  BubbleWrap.require('motion/media/**/*.rb') do
@@ -85,7 +85,7 @@ module BubbleWrap
85
85
  end
86
86
 
87
87
  def frameworks(app_frameworks=nil)
88
- frameworks = ['UIKit', 'Foundation', 'CoreGraphics'] +
88
+ frameworks = ['Foundation', 'CoreGraphics'] +
89
89
  paths.values.map(&:frameworks)
90
90
  frameworks += app_frameworks if app_frameworks
91
91
  frameworks.flatten.compact.sort.uniq
@@ -1,4 +1,4 @@
1
1
  module BubbleWrap
2
- VERSION = '1.4.0' unless defined?(BubbleWrap::VERSION)
3
- MIN_MOTION_VERSION = '2.0'
2
+ VERSION = '1.5.0.rc1' unless defined?(BubbleWrap::VERSION)
3
+ MIN_MOTION_VERSION = '2.17'
4
4
  end
@@ -34,9 +34,21 @@ module BubbleWrap
34
34
  @rear ||= Camera.new(:rear)
35
35
  end
36
36
 
37
+ def self.available?
38
+ UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceTypeCamera)
39
+ end
40
+
37
41
  # For uploading photos from the library.
38
- def self.any
39
- @any ||= Camera.new
42
+ class << self
43
+ def any
44
+ @any ||= Camera.new
45
+ end
46
+ alias_method "photo_library", "any"
47
+ end
48
+
49
+ def popover_from(view)
50
+ @popover_in_view = view
51
+ self
40
52
  end
41
53
 
42
54
  def initialize(location = :none)
@@ -78,6 +90,7 @@ module BubbleWrap
78
90
  # end
79
91
  def picture(options = {}, presenting_controller = nil, &block)
80
92
  @callback = block
93
+ @callback.weak! if @callback && BubbleWrap.use_weak_callbacks?
81
94
 
82
95
  @options = options
83
96
  @options[:allows_editing] = false if not @options.has_key? :allows_editing
@@ -124,7 +137,19 @@ module BubbleWrap
124
137
 
125
138
  presenting_controller ||= App.window.rootViewController.presentedViewController # May be nil, but handles use case of container views
126
139
  presenting_controller ||= App.window.rootViewController
127
- presenting_controller.presentViewController(self.picker, animated:@options[:animated], completion: lambda {})
140
+
141
+ # use popover for iPad (ignore on iPhone)
142
+ if Device.ipad? and source_type==UIImagePickerControllerSourceTypePhotoLibrary and @popover_in_view
143
+ @popover = UIPopoverController.alloc.initWithContentViewController(picker)
144
+ @popover.presentPopoverFromRect(@popover_in_view.bounds, inView:@popover_in_view, permittedArrowDirections:UIPopoverArrowDirectionAny, animated:@options[:animated])
145
+ else
146
+ presenting_controller.presentViewController(self.picker, animated:@options[:animated], completion: lambda {})
147
+ end
148
+ end
149
+
150
+ # iPad popover is dismissed
151
+ def popoverControllerDidDismissPopover(popoverController)
152
+ @popover = nil
128
153
  end
129
154
 
130
155
  ##########
@@ -154,6 +179,11 @@ module BubbleWrap
154
179
 
155
180
  @callback.call(callback_info)
156
181
  dismiss
182
+ # iPad popover? close it
183
+ if @popover
184
+ @popover.dismissPopoverAnimated(@options[:animated])
185
+ @popover = nil
186
+ end
157
187
  end
158
188
 
159
189
  ##########
@@ -34,12 +34,22 @@ module BubbleWrap
34
34
  def any
35
35
  @any ||= BubbleWrap::Device::Camera.any
36
36
  end
37
+ # alias for any
38
+ def photo_library
39
+ any
40
+ end
37
41
 
38
42
  # Should always return true, since picking images from *some* source is always possible
39
43
  # @return [TrueClass]
40
44
  def any?
41
45
  !!any
42
46
  end
47
+
48
+ # Verifies that the device running has a physical camera.
49
+ # @return [TrueClass, FalseClass] true will be returned if the device has a physical camera, false otherwise.
50
+ def available?
51
+ BubbleWrap::Device::Camera.available?
52
+ end
43
53
  end
44
54
  end
45
55
  end
data/motion/core/kvo.rb CHANGED
@@ -21,12 +21,26 @@ module BubbleWrap
21
21
  COLLECTION_OPERATIONS = [ NSKeyValueChangeInsertion, NSKeyValueChangeRemoval, NSKeyValueChangeReplacement ]
22
22
  DEFAULT_OPTIONS = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
23
23
 
24
- def observe(target, key_path, &block)
24
+ def observe(*arguments, &block)
25
+ unless [1,2].include?(arguments.length)
26
+ raise ArgumentError, "wrong number of arguments (#{arguments.length} for 1 or 2)"
27
+ end
28
+
29
+ key_path = arguments.pop
30
+ target = arguments.pop || self
31
+
25
32
  target.addObserver(self, forKeyPath:key_path, options:DEFAULT_OPTIONS, context:nil) unless registered?(target, key_path)
26
33
  add_observer_block(target, key_path, &block)
27
34
  end
28
35
 
29
- def unobserve(target, key_path)
36
+ def unobserve(*arguments)
37
+ unless [1,2].include?(arguments.length)
38
+ raise ArgumentError, "wrong number of arguments (#{arguments.length} for 1 or 2)"
39
+ end
40
+
41
+ key_path = arguments.pop
42
+ target = arguments.pop || self
43
+
30
44
  return unless registered?(target, key_path)
31
45
 
32
46
  target.removeObserver(self, forKeyPath:key_path)
@@ -54,6 +68,8 @@ module BubbleWrap
54
68
  def add_observer_block(target, key_path, &block)
55
69
  return if target.nil? || key_path.nil? || block.nil?
56
70
 
71
+ block.weak! if BubbleWrap.use_weak_callbacks?
72
+
57
73
  @targets ||= {}
58
74
  @targets[target] ||= {}
59
75
  @targets[target][key_path.to_s] ||= []
@@ -4,6 +4,7 @@ class NSNotificationCenter
4
4
  end
5
5
 
6
6
  def observe(name, object=nil, &proc)
7
+ proc.weak! if proc && BubbleWrap.use_weak_callbacks?
7
8
  observer = self.addObserverForName(name, object:object, queue:NSOperationQueue.mainQueue, usingBlock:proc)
8
9
  observers << observer
9
10
  observer
data/motion/core/time.rb CHANGED
@@ -9,6 +9,11 @@ class Time
9
9
  cached_date_formatter("yyyy-MM-dd'T'HH:mm:ssZZZZZ").
10
10
  dateFromString(time)
11
11
  end
12
+
13
+ def self.iso8601_with_fractional_seconds(time)
14
+ cached_date_formatter("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").
15
+ dateFromString(time)
16
+ end
12
17
 
13
18
  private
14
19
 
data/motion/http/query.rb CHANGED
@@ -30,6 +30,10 @@ module BubbleWrap; module HTTP; class Query
30
30
  def initialize(url_string, http_method = :get, options={})
31
31
  @method = http_method.upcase.to_s
32
32
  @delegator = options.delete(:action) || self
33
+ if @delegator.respond_to?("weak!")
34
+ @delegator.weak! if BubbleWrap.use_weak_callbacks?
35
+ end
36
+
33
37
  @payload = options.delete(:payload)
34
38
  @encoding = options.delete(:encoding) || NSUTF8StringEncoding
35
39
  @files = options.delete(:files)
@@ -53,6 +57,7 @@ module BubbleWrap; module HTTP; class Query
53
57
  @original_url = @url.copy
54
58
 
55
59
  @connection = create_connection(request, self)
60
+ @connection.scheduleInRunLoop(NSRunLoop.currentRunLoop, forMode:NSRunLoopCommonModes)
56
61
  @connection.start
57
62
 
58
63
  show_status_indicator true
@@ -269,20 +274,21 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
269
274
  end
270
275
 
271
276
  def parse_file(key, value)
272
- if value.is_a?(Hash)
273
- raise(InvalidFileError, "You need to supply a `:data` entry in #{value} for file '#{key}' in your HTTP `:files`") if value[:data].nil?
274
- {data: value[:data], filename: value[:filename] || key}
275
- else
276
- {data: value, filename: key}
277
- end
277
+ value = {data: value} unless value.is_a?(Hash)
278
+ raise(InvalidFileError, "You need to supply a `:data` entry in #{value} for file '#{key}' in your HTTP `:files`") if value[:data].nil?
279
+ {
280
+ data: value[:data],
281
+ filename: value.fetch(:filename, key),
282
+ content_type: value.fetch(:content_type, "application/octet-stream")
283
+ }
278
284
  end
279
285
 
280
286
  def append_files(body)
281
287
  @files.each do |key, value|
282
288
  file = parse_file(key, value)
283
289
  s = "--#{@boundary}\r\n"
284
- s += "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{file[:filename]}\"\r\n"
285
- s += "Content-Type: application/octet-stream\r\n\r\n"
290
+ s += "Content-Disposition: attachment; name=\"#{key}\"; filename=\"#{file[:filename]}\"\r\n"
291
+ s += "Content-Type: #{file[:content_type]}\r\n\r\n"
286
292
  file_data = NSMutableData.new
287
293
  file_data.appendData(s.to_encoded_data @encoding)
288
294
  file_data.appendData(file[:data])
@@ -381,7 +387,7 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
381
387
 
382
388
  # This is a temporary method used for mocking.
383
389
  def create_connection(request, delegate)
384
- NSURLConnection.connectionWithRequest(request, delegate:delegate)
390
+ NSURLConnection.alloc.initWithRequest(request, delegate:delegate, startImmediately:false)
385
391
  end
386
392
 
387
393
  end; end; end
@@ -50,6 +50,7 @@ module BubbleWrap
50
50
  # end
51
51
  def get(options = {}, &block)
52
52
  @callback = block
53
+ @callback.weak! if @callback && BubbleWrap.use_weak_callbacks?
53
54
  @options = options
54
55
 
55
56
  @options[:significant] = false if @options[:significant].nil?
@@ -112,11 +113,11 @@ module BubbleWrap
112
113
  # CLLocationManagerDelegate Methods
113
114
  def locationManager(manager, didUpdateToLocation:newLocation, fromLocation:oldLocation)
114
115
  if @options[:once]
115
- @callback.call(newLocation)
116
+ @callback && @callback.call(newLocation)
116
117
  @callback = proc { |result| }
117
118
  stop
118
119
  else
119
- @callback.call({to: newLocation, from: oldLocation})
120
+ @callback && @callback.call({to: newLocation, from: oldLocation})
120
121
  end
121
122
  end
122
123
 
data/motion/mail/mail.rb CHANGED
@@ -26,11 +26,12 @@ module BubbleWrap
26
26
  @delegate = options[:delegate] || App.window.rootViewController
27
27
 
28
28
  @callback = callback
29
+ @callback.weak! if @callback && BubbleWrap.use_weak_callbacks?
29
30
 
30
31
  @mail_controller = create_mail_controller(options)
31
32
 
32
33
  @mailer_is_animated = options[:animated] == false ? false : true
33
- @delegate.presentModalViewController(@mail_controller, animated: @mailer_is_animated)
34
+ @delegate.presentViewController(@mail_controller, animated: @mailer_is_animated, completion: options[:completion])
34
35
  end
35
36
 
36
37
  def create_mail_controller(options={})