bubble-wrap 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +0 -1
- data/.yardopts +2 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +24 -0
- data/HACKING.md +2 -2
- data/README.md +363 -21
- data/Rakefile +6 -2
- data/lib/bubble-wrap.rb +0 -1
- data/lib/bubble-wrap/all.rb +4 -0
- data/lib/bubble-wrap/camera.rb +7 -0
- data/lib/bubble-wrap/core.rb +3 -2
- data/lib/bubble-wrap/ext/motion_project_app.rb +2 -2
- data/lib/bubble-wrap/http.rb +1 -0
- data/lib/bubble-wrap/loader.rb +19 -12
- data/lib/bubble-wrap/location.rb +6 -0
- data/lib/bubble-wrap/reactor.rb +10 -0
- data/lib/bubble-wrap/requirement.rb +11 -3
- data/lib/bubble-wrap/rss_parser.rb +2 -0
- data/lib/bubble-wrap/ui.rb +4 -0
- data/lib/bubble-wrap/version.rb +1 -1
- data/motion/core.rb +8 -2
- data/motion/core/app.rb +34 -6
- data/motion/core/device.rb +10 -1
- data/motion/core/device/camera.rb +219 -0
- data/motion/core/device/camera_wrapper.rb +45 -0
- data/motion/core/ns_url_request.rb +10 -0
- data/motion/core/persistence.rb +7 -0
- data/motion/core/pollute.rb +1 -2
- data/motion/core/string.rb +23 -0
- data/motion/http.rb +142 -83
- data/motion/location/location.rb +152 -0
- data/motion/location/pollute.rb +5 -0
- data/motion/reactor.rb +105 -0
- data/motion/reactor/default_deferrable.rb +9 -0
- data/motion/reactor/deferrable.rb +126 -0
- data/motion/reactor/eventable.rb +24 -0
- data/motion/reactor/future.rb +22 -0
- data/motion/reactor/periodic_timer.rb +27 -0
- data/motion/reactor/queue.rb +60 -0
- data/motion/reactor/timer.rb +25 -0
- data/motion/rss_parser.rb +131 -0
- data/motion/shortcut.rb +18 -0
- data/motion/{core → ui}/gestures.rb +15 -9
- data/motion/ui/pollute.rb +5 -0
- data/motion/{core → ui}/ui_control.rb +0 -0
- data/motion/{core → ui}/ui_view_controller.rb +0 -0
- data/resources/atom.xml +1705 -0
- data/spec/lib/bubble-wrap/ext/motion_project_app_spec.rb +7 -11
- data/spec/lib/bubble-wrap/requirement_spec.rb +4 -4
- data/spec/lib/bubble-wrap_spec.rb +2 -2
- data/spec/motion/core/app_spec.rb +118 -14
- data/spec/motion/core/device/camera_spec.rb +130 -0
- data/spec/motion/core/device/camera_wrapper_spec.rb +45 -0
- data/spec/motion/core/device_spec.rb +0 -50
- data/spec/motion/core/gestures_spec.rb +5 -0
- data/spec/motion/core/persistence_spec.rb +24 -2
- data/spec/motion/core/string_spec.rb +55 -0
- data/spec/motion/core_spec.rb +72 -1
- data/spec/motion/http_spec.rb +100 -65
- data/spec/motion/location/location_spec.rb +152 -0
- data/spec/motion/reactor/eventable_spec.rb +40 -0
- data/spec/motion/reactor_spec.rb +163 -0
- data/spec/motion/rss_parser_spec.rb +36 -0
- metadata +75 -16
data/Rakefile
CHANGED
@@ -4,12 +4,17 @@ require 'motion/project'
|
|
4
4
|
Bundler.setup
|
5
5
|
Bundler.require
|
6
6
|
|
7
|
+
require 'bubble-wrap/all'
|
7
8
|
require 'bubble-wrap/test'
|
8
9
|
|
9
10
|
Motion::Project::App.setup do |app|
|
10
11
|
app.name = 'testSuite'
|
11
12
|
app.identifier = 'io.bubblewrap.testSuite'
|
12
|
-
app.specs_dir = './spec/motion'
|
13
|
+
app.specs_dir = './spec/motion/'
|
14
|
+
# Hold your breath, we're going API spelunking!
|
15
|
+
spec_files = app.spec_files + Dir.glob(File.join(app.specs_dir, '**/*.rb'))
|
16
|
+
spec_files.uniq!
|
17
|
+
app.instance_variable_set(:@spec_files, spec_files)
|
13
18
|
end
|
14
19
|
|
15
20
|
namespace :spec do
|
@@ -21,4 +26,3 @@ namespace :spec do
|
|
21
26
|
|
22
27
|
task :all => [:lib, :motion]
|
23
28
|
end
|
24
|
-
|
data/lib/bubble-wrap.rb
CHANGED
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'bubble-wrap/loader'
|
2
|
+
BubbleWrap.require('motion/core/device.rb')
|
3
|
+
BubbleWrap.require('motion/core/device/**/*.rb') do
|
4
|
+
file('motion/core/device/camera_wrapper.rb').depends_on 'motion/core/device/camera.rb'
|
5
|
+
file('motion/core/device/camera.rb').depends_on 'motion/core/device.rb'
|
6
|
+
file('motion/core/device/screen.rb').depends_on 'motion/core/device.rb'
|
7
|
+
end
|
data/lib/bubble-wrap/core.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'bubble-wrap/loader'
|
2
2
|
BubbleWrap.require('motion/core.rb')
|
3
|
-
BubbleWrap.require('motion/core/**/*.rb') do
|
3
|
+
BubbleWrap.require('motion/core/**/*.rb') do
|
4
|
+
file('motion/core/device/camera.rb').depends_on 'motion/core/device.rb'
|
4
5
|
file('motion/core/device/screen.rb').depends_on 'motion/core/device.rb'
|
5
6
|
file('motion/core/pollute.rb').depends_on 'motion/core/ns_index_path.rb'
|
6
|
-
file('motion/core/pollute.rb').depends_on 'motion/core/ui_control.rb'
|
7
7
|
end
|
8
|
+
require 'bubble-wrap/ui'
|
@@ -6,9 +6,9 @@ module BubbleWrap
|
|
6
6
|
base.instance_eval do
|
7
7
|
def setup_with_bubblewrap(&block)
|
8
8
|
bw_config = proc do |app|
|
9
|
-
app.files =
|
9
|
+
app.files = ::BubbleWrap::Requirement.files(app.files)
|
10
10
|
app.files_dependencies ::BubbleWrap::Requirement.files_dependencies
|
11
|
-
app.frameworks =
|
11
|
+
app.frameworks = ::BubbleWrap::Requirement.frameworks(app.frameworks)
|
12
12
|
block.call(app) unless block.nil?
|
13
13
|
end
|
14
14
|
configs.each_value &bw_config
|
data/lib/bubble-wrap/http.rb
CHANGED
data/lib/bubble-wrap/loader.rb
CHANGED
@@ -2,22 +2,29 @@ unless defined?(Motion::Project::Config)
|
|
2
2
|
raise "This file must be required within a RubyMotion project Rakefile."
|
3
3
|
end
|
4
4
|
|
5
|
-
|
6
|
-
require 'bubble-wrap/ext'
|
7
|
-
require 'bubble-wrap/requirement'
|
5
|
+
unless defined?(BubbleWrap::LOADER_PRESENT)
|
8
6
|
|
9
|
-
|
7
|
+
require 'bubble-wrap/version' unless defined?(VERSION)
|
8
|
+
require 'bubble-wrap/ext'
|
9
|
+
require 'bubble-wrap/requirement'
|
10
10
|
|
11
|
-
|
11
|
+
module BubbleWrap
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
LOADER_PRESENT=true
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def root
|
17
|
+
File.expand_path('../../../', __FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def require(file_spec, &block)
|
21
|
+
Requirement.scan(caller.first, file_spec, &block)
|
22
|
+
end
|
16
23
|
|
17
|
-
def require(file_spec, &block)
|
18
|
-
Requirement.scan(caller.first, file_spec, &block)
|
19
24
|
end
|
20
25
|
|
21
|
-
|
26
|
+
BW = BubbleWrap unless defined?(BW)
|
22
27
|
|
23
|
-
BW
|
28
|
+
BW.require 'motion/shortcut.rb'
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require 'bubble-wrap/loader'
|
2
|
+
BubbleWrap.require('motion/core/string.rb')
|
3
|
+
BubbleWrap.require('motion/location/**/*.rb') do
|
4
|
+
file('motion/location/pollute.rb').depends_on 'motion/location/location.rb'
|
5
|
+
file('motion/location/location.rb').uses_framework('CoreLocation')
|
6
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'bubble-wrap/loader'
|
2
|
+
|
3
|
+
BW.require 'motion/reactor.rb'
|
4
|
+
BW.require 'motion/reactor/**/*.rb' do
|
5
|
+
file('motion/reactor.rb').depends_on Dir.glob('motion/reactor/**/*.rb')
|
6
|
+
file('motion/reactor/timer.rb').depends_on 'motion/reactor/eventable.rb'
|
7
|
+
file('motion/reactor/periodic_timer.rb').depends_on 'motion/reactor/eventable.rb'
|
8
|
+
file('motion/reactor/deferrable.rb').depends_on ['motion/reactor/timer.rb', 'motion/reactor/future.rb']
|
9
|
+
file('motion/reactor/default_deferrable.rb').depends_on 'motion/reactor/deferrable.rb'
|
10
|
+
end
|
@@ -57,6 +57,7 @@ module BubbleWrap
|
|
57
57
|
Dir.glob(File.expand_path(file_spec, root)).each do |file|
|
58
58
|
p = new(file,root)
|
59
59
|
self.paths[p.relative] = p
|
60
|
+
p.depends_on('motion/shortcut.rb') unless p.relative == 'motion/shortcut.rb'
|
60
61
|
end
|
61
62
|
self.class_eval(&block) if block
|
62
63
|
end
|
@@ -65,8 +66,14 @@ module BubbleWrap
|
|
65
66
|
paths.fetch(relative)
|
66
67
|
end
|
67
68
|
|
68
|
-
def files
|
69
|
-
paths.values.map(&:to_s)
|
69
|
+
def files(app_files=nil)
|
70
|
+
files = paths.values.map(&:to_s)
|
71
|
+
files += app_files if app_files
|
72
|
+
files.uniq
|
73
|
+
end
|
74
|
+
|
75
|
+
def clear!
|
76
|
+
paths.select! { |k,v| v.relative == 'motion/shortcut.rb' }
|
70
77
|
end
|
71
78
|
|
72
79
|
def files_dependencies
|
@@ -77,9 +84,10 @@ module BubbleWrap
|
|
77
84
|
deps
|
78
85
|
end
|
79
86
|
|
80
|
-
def frameworks
|
87
|
+
def frameworks(app_frameworks=nil)
|
81
88
|
frameworks = ['UIKit', 'Foundation', 'CoreGraphics'] +
|
82
89
|
paths.values.map(&:frameworks)
|
90
|
+
frameworks += app_frameworks if app_frameworks
|
83
91
|
frameworks.flatten.compact.sort.uniq
|
84
92
|
end
|
85
93
|
|
data/lib/bubble-wrap/version.rb
CHANGED
data/motion/core.rb
CHANGED
@@ -11,7 +11,7 @@ module BubbleWrap
|
|
11
11
|
UIColor.colorWithRed((r/255.0), green:(g/255.0), blue:(b/255.0), alpha:a)
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def localized_string(key, value)
|
15
15
|
NSBundle.mainBundle.localizedStringForKey(key, value:value, table:nil)
|
16
16
|
end
|
17
17
|
|
@@ -20,5 +20,11 @@ module BubbleWrap
|
|
20
20
|
NSLog arg.inspect
|
21
21
|
end
|
22
22
|
|
23
|
+
def create_uuid
|
24
|
+
uuid = CFUUIDCreate(nil)
|
25
|
+
uuid_string = CFUUIDCreateString(nil, uuid)
|
26
|
+
CFRelease(uuid)
|
27
|
+
uuid_string
|
28
|
+
end
|
29
|
+
|
23
30
|
end
|
24
|
-
BW = BubbleWrap
|
data/motion/core/app.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Provides a module to store global states
|
1
|
+
# Provides a module to store global states
|
2
2
|
#
|
3
3
|
module BubbleWrap
|
4
4
|
module App
|
@@ -26,12 +26,30 @@ module BubbleWrap
|
|
26
26
|
NSUserDefaults.standardUserDefaults
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
# Displays a UIAlertView.
|
30
|
+
#
|
31
|
+
# title - The title as a String.
|
32
|
+
# args - The title of the cancel button as a String, or a Hash of options.
|
33
|
+
# (Default: { cancel_button_title: 'OK' })
|
34
|
+
# cancel_button_title - The title of the cancel button as a String.
|
35
|
+
# message - The main message as a String.
|
36
|
+
# block - Yields the alert object if a block is given, and does so before the alert is shown.
|
37
|
+
def alert(title, *args, &block)
|
38
|
+
options = { cancel_button_title: 'OK' }
|
39
|
+
options.merge!(args.pop) if args.last.is_a?(Hash)
|
40
|
+
|
41
|
+
if args.size > 0 && args.first.is_a?(String)
|
42
|
+
options[:cancel_button_title] = args.shift
|
43
|
+
end
|
44
|
+
|
45
|
+
alert = UIAlertView.alloc.initWithTitle title,
|
46
|
+
message: options[:message],
|
47
|
+
delegate: nil,
|
48
|
+
cancelButtonTitle: options[:cancel_button_title],
|
34
49
|
otherButtonTitles: nil
|
50
|
+
|
51
|
+
yield(alert) if block_given?
|
52
|
+
|
35
53
|
alert.show
|
36
54
|
alert
|
37
55
|
end
|
@@ -47,6 +65,16 @@ module BubbleWrap
|
|
47
65
|
repeats: false)
|
48
66
|
end
|
49
67
|
|
68
|
+
# Opens an url (string or instance of `NSURL`)
|
69
|
+
# in the device's web browser.
|
70
|
+
# Usage Example:
|
71
|
+
# App.open_url("http://matt.aimonetti.net")
|
72
|
+
def open_url(url)
|
73
|
+
unless url.is_a?(NSURL)
|
74
|
+
url = NSURL.URLWithString(url)
|
75
|
+
end
|
76
|
+
UIApplication.sharedApplication.openURL(url)
|
77
|
+
end
|
50
78
|
|
51
79
|
@states = {}
|
52
80
|
|
data/motion/core/device.rb
CHANGED
@@ -14,15 +14,24 @@ module BubbleWrap
|
|
14
14
|
idiom == UIUserInterfaceIdiomPad
|
15
15
|
end
|
16
16
|
|
17
|
+
# Use this to make a DSL-style call for picking images
|
18
|
+
# @example Device.camera.front
|
19
|
+
# @return [Device::Camera::CameraWrapper]
|
20
|
+
def camera
|
21
|
+
BubbleWrap::Device::CameraWrapper
|
22
|
+
end
|
23
|
+
|
17
24
|
# Verifies that the device running has a front facing camera.
|
18
25
|
# @return [TrueClass, FalseClass] true will be returned if the device has a front facing camera, false otherwise.
|
19
|
-
def front_camera?
|
26
|
+
def front_camera?
|
27
|
+
p "This method (front_camera?) is DEPRECATED. Transition to using Device.camera.front?"
|
20
28
|
picker.isCameraDeviceAvailable(UIImagePickerControllerCameraDeviceFront)
|
21
29
|
end
|
22
30
|
|
23
31
|
# Verifies that the device running has a rear facing camera.
|
24
32
|
# @return [TrueClass, FalseClass] true will be returned if the device has a rear facing camera, false otherwise.
|
25
33
|
def rear_camera?(picker=UIImagePickerController)
|
34
|
+
p "This method (rear_camera?) is DEPRECATED. Transition to using Device.camera.rear?"
|
26
35
|
picker.isCameraDeviceAvailable(UIImagePickerControllerCameraDeviceRear)
|
27
36
|
end
|
28
37
|
|
@@ -0,0 +1,219 @@
|
|
1
|
+
# Provides a nice DSL for interacting with the standard
|
2
|
+
# UIImagePickerController
|
3
|
+
#
|
4
|
+
module BubbleWrap
|
5
|
+
module Device
|
6
|
+
class Camera
|
7
|
+
module Error
|
8
|
+
SOURCE_TYPE_NOT_AVAILABLE=0
|
9
|
+
INVALID_MEDIA_TYPE=1
|
10
|
+
MEDIA_TYPE_NOT_AVAILABLE=2
|
11
|
+
INVALID_CAMERA_LOCATION=3
|
12
|
+
CANCELED=1000
|
13
|
+
end
|
14
|
+
|
15
|
+
MEDIA_TYPE_HASH = {movie: KUTTypeMovie, image: KUTTypeImage}
|
16
|
+
|
17
|
+
# The camera location; if :none, then we can't use source_type: :camera
|
18
|
+
# in #picture
|
19
|
+
# [:front, :rear, :none]
|
20
|
+
attr_accessor :location
|
21
|
+
|
22
|
+
def self.front
|
23
|
+
return nil if not UIImagePickerController.isCameraDeviceAvailable(UIImagePickerControllerCameraDeviceFront)
|
24
|
+
Camera.new(:front).retain
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.rear
|
28
|
+
return nil if not UIImagePickerController.isCameraDeviceAvailable(UIImagePickerControllerCameraDeviceRear)
|
29
|
+
Camera.new(:rear).retain
|
30
|
+
end
|
31
|
+
|
32
|
+
# For uploading photos from the library.
|
33
|
+
def self.any
|
34
|
+
Camera.new.retain
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(location = :none)
|
38
|
+
self.location = location
|
39
|
+
end
|
40
|
+
|
41
|
+
def location=(location)
|
42
|
+
if not [:front, :rear, :none].member? location
|
43
|
+
raise Error::INVALID_CAMERA_LOCATION, "#{location} is not a valid camera location"
|
44
|
+
end
|
45
|
+
@location = location
|
46
|
+
end
|
47
|
+
|
48
|
+
def flash?
|
49
|
+
return false if self.location == :none
|
50
|
+
UIImagePickerController.isFlashAvailableForCameraDevice(camera_device)
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param [Hash] options to open the UIImagePickerController with
|
54
|
+
# the form {
|
55
|
+
# source_type: :photo_library, :camera, or :saved_photos_album; default :photo_library
|
56
|
+
# media_types: [] containing :image and/or :movie; default [:image]
|
57
|
+
# allows_editing: true/false; default false
|
58
|
+
# animated: true/false; default true
|
59
|
+
# }
|
60
|
+
#
|
61
|
+
# @param [UIViewController] view controller from which to present the image picker;
|
62
|
+
# if nil, uses the keyWindow's rootViewController.
|
63
|
+
#
|
64
|
+
# @block for callback. takes one argument.
|
65
|
+
# - On error or cancelled, is called with a hash {error: BW::Camera::Error::<Type>}
|
66
|
+
# - On success, is called with a hash with a possible set of keys
|
67
|
+
# [:media_type, :original_image, :edited_image, :crop_rect, :media_url,
|
68
|
+
# :reference_url, :media_metadata]
|
69
|
+
#
|
70
|
+
# Example
|
71
|
+
# BW::Camera.picture(source_type: :photo_library, media_types: [:image]) do |result|
|
72
|
+
# image_view = UIImageView.alloc.initWithImage(result[:original_image])
|
73
|
+
# end
|
74
|
+
def picture(options = {}, presenting_controller = nil, &block)
|
75
|
+
@callback = block
|
76
|
+
|
77
|
+
@options = options
|
78
|
+
@options[:allows_editing] = false if not @options.has_key? :allows_editing
|
79
|
+
@options[:animated] = true if not @options.has_key? :animated
|
80
|
+
@options[:media_types] = [:image] if not @options.has_key? :media_types
|
81
|
+
|
82
|
+
# If we're using Camera.any, by default use photo library
|
83
|
+
if !@options.has_key?(:source_type) and self.location == :none
|
84
|
+
@options[:source_type] = :photo_library
|
85
|
+
# If we're using a real Camera, by default use the camera.
|
86
|
+
elsif !@options.has_key?(:source_type)
|
87
|
+
@options[:source_type] = :camera
|
88
|
+
end
|
89
|
+
|
90
|
+
source_type = const_int_get("UIImagePickerControllerSourceType", @options[:source_type])
|
91
|
+
if not Camera.source_type_available?(source_type)
|
92
|
+
error(Error::SOURCE_TYPE_NOT_AVAILABLE) and return
|
93
|
+
end
|
94
|
+
|
95
|
+
media_types = @options[:media_types].collect { |mt| symbol_to_media_type(mt) }
|
96
|
+
if media_types.member? nil
|
97
|
+
error(Error::INVALID_MEDIA_TYPE) and return
|
98
|
+
end
|
99
|
+
|
100
|
+
media_types.each { |media_type|
|
101
|
+
if not Camera.media_type_available?(media_type, for_source_type: source_type)
|
102
|
+
error(Error::MEDIA_TYPE_NOT_AVAILABLE) and return
|
103
|
+
end
|
104
|
+
}
|
105
|
+
|
106
|
+
self.picker.delegate = self
|
107
|
+
self.picker.sourceType = source_type
|
108
|
+
self.picker.mediaTypes = media_types
|
109
|
+
self.picker.allowsEditing = @options[:allows_editing]
|
110
|
+
|
111
|
+
if source_type == :camera && ![:front, :rear].member?(self.location)
|
112
|
+
raise Error::INVALID_CAMERA_LOCATION, "Can't use camera location #{self.location} with source type :camera"
|
113
|
+
end
|
114
|
+
|
115
|
+
if source_type == :camera
|
116
|
+
self.picker.cameraDevice = camera_device
|
117
|
+
end
|
118
|
+
|
119
|
+
presenting_controller ||= UIApplication.sharedApplication.keyWindow.rootViewController
|
120
|
+
presenting_controller.presentViewController(self.picker, animated:@options[:animated], completion: lambda {})
|
121
|
+
end
|
122
|
+
|
123
|
+
##########
|
124
|
+
# UIImagePickerControllerDelegate Methods
|
125
|
+
def imagePickerControllerDidCancel(picker)
|
126
|
+
error(Error::CANCELED)
|
127
|
+
dismiss
|
128
|
+
end
|
129
|
+
|
130
|
+
# Takes the default didFinishPickingMediaWithInfo hash,
|
131
|
+
# transforms the keys to be nicer symbols of :this_form
|
132
|
+
# instead of UIImagePickerControllerThisForm, and then sends it
|
133
|
+
# to the callback
|
134
|
+
def imagePickerController(picker, didFinishPickingMediaWithInfo: info)
|
135
|
+
delete_keys = []
|
136
|
+
callback_info = {}
|
137
|
+
|
138
|
+
info.keys.each { |k|
|
139
|
+
nice_key = k.gsub("UIImagePickerController", "").underscore.to_sym
|
140
|
+
val = info[k]
|
141
|
+
callback_info[nice_key] = val
|
142
|
+
info.delete k
|
143
|
+
}
|
144
|
+
|
145
|
+
if media_type = callback_info[:media_type]
|
146
|
+
callback_info[:media_type] = media_type_to_symbol(media_type)
|
147
|
+
end
|
148
|
+
|
149
|
+
@callback.call(callback_info)
|
150
|
+
dismiss
|
151
|
+
end
|
152
|
+
|
153
|
+
##########
|
154
|
+
# Short Helper Methods
|
155
|
+
def picker
|
156
|
+
@picker_klass ||= UIImagePickerController
|
157
|
+
@picker ||= @picker_klass.alloc.init
|
158
|
+
end
|
159
|
+
|
160
|
+
def dismiss
|
161
|
+
self.picker.dismissViewControllerAnimated(@options[:animated], completion: lambda {})
|
162
|
+
end
|
163
|
+
|
164
|
+
# @param [UIImagePickerControllerSourceType] source_type to check
|
165
|
+
def self.source_type_available?(source_type)
|
166
|
+
UIImagePickerController.isSourceTypeAvailable(source_type)
|
167
|
+
end
|
168
|
+
|
169
|
+
# @param [String] (either KUTTypeMovie or KUTTypeImage)
|
170
|
+
# @param [UIImagePickerControllerSourceType]
|
171
|
+
def self.media_type_available?(media_type, for_source_type: source_type)
|
172
|
+
UIImagePickerController.availableMediaTypesForSourceType(source_type).member? media_type
|
173
|
+
end
|
174
|
+
|
175
|
+
private
|
176
|
+
def camera_device
|
177
|
+
const_int_get("UIImagePickerControllerCameraDevice", self.location)
|
178
|
+
end
|
179
|
+
|
180
|
+
# ex media_type_to_symbol(KUTTypeMovie) => :movie
|
181
|
+
def media_type_to_symbol(media_type)
|
182
|
+
MEDIA_TYPE_HASH.invert[media_type]
|
183
|
+
end
|
184
|
+
|
185
|
+
# ex symbol_to_media_type(:movie) => :KUTTypeMovie
|
186
|
+
def symbol_to_media_type(symbol)
|
187
|
+
MEDIA_TYPE_HASH[symbol]
|
188
|
+
end
|
189
|
+
|
190
|
+
def error(type)
|
191
|
+
@callback.call({ error: type })
|
192
|
+
end
|
193
|
+
|
194
|
+
# @param [String] base of the constant
|
195
|
+
# @param [Integer, String, Symbol] the
|
196
|
+
# @return [Integer] the constant for this base
|
197
|
+
# Examples
|
198
|
+
# const_int_get("UIReturnKey", :done) => UIReturnKeyDone == 9
|
199
|
+
# const_int_get("UIReturnKey", "done") => UIReturnKeyDone == 9
|
200
|
+
# const_int_get("UIReturnKey", 9) => 9
|
201
|
+
def const_int_get(base, value)
|
202
|
+
return value if value.is_a? Numeric
|
203
|
+
value = value.to_s.camelize
|
204
|
+
Kernel.const_get("#{base}#{value}")
|
205
|
+
end
|
206
|
+
|
207
|
+
# Looks like RubyMotion adds UIKit constants
|
208
|
+
# at compile time. If you don't use these
|
209
|
+
# directly in your code, they don't get added
|
210
|
+
# to Kernel and const_int_get crashes.
|
211
|
+
def load_constants_hack
|
212
|
+
[UIImagePickerControllerSourceTypePhotoLibrary, UIImagePickerControllerSourceTypeCamera,
|
213
|
+
UIImagePickerControllerSourceTypeSavedPhotosAlbum
|
214
|
+
]
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
::Camera = BubbleWrap::Device::Camera
|