bubble-wrap 1.1.2 → 1.1.3

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 (40) hide show
  1. data/Gemfile.lock +1 -1
  2. data/README.md +32 -9
  3. data/Rakefile +1 -5
  4. data/lib/bubble-wrap/all.rb +1 -1
  5. data/lib/bubble-wrap/http.rb +1 -0
  6. data/lib/bubble-wrap/media.rb +8 -0
  7. data/lib/bubble-wrap/version.rb +1 -1
  8. data/motion/core/app.rb +5 -0
  9. data/motion/core/device.rb +1 -1
  10. data/motion/core/json.rb +1 -0
  11. data/motion/core/ns_url_request.rb +4 -2
  12. data/motion/core/persistence.rb +7 -1
  13. data/motion/core/string.rb +2 -2
  14. data/motion/http.rb +81 -65
  15. data/motion/location/location.rb +2 -2
  16. data/motion/media/media.rb +15 -0
  17. data/motion/media/player.rb +139 -0
  18. data/motion/test_suite_delegate.rb +1 -0
  19. data/resources/test.mp3 +0 -0
  20. data/samples/camera/Gemfile +3 -0
  21. data/samples/camera/README.md +4 -0
  22. data/samples/camera/Rakefile +9 -0
  23. data/samples/camera/app/app_delegate.rb +8 -0
  24. data/samples/camera/app/controllers/camera_controller.rb +61 -0
  25. data/samples/camera/spec/main_spec.rb +9 -0
  26. data/samples/location/.gitignore +5 -0
  27. data/samples/location/Gemfile +3 -0
  28. data/samples/location/README.md +4 -0
  29. data/samples/location/Rakefile +10 -0
  30. data/samples/location/app/app_delegate.rb +8 -0
  31. data/samples/location/app/controllers/image_list_controller.rb +30 -0
  32. data/samples/location/app/models/places.rb +15 -0
  33. data/samples/location/spec/main_spec.rb +9 -0
  34. data/spec/motion/core/app_spec.rb +7 -1
  35. data/spec/motion/core/json_spec.rb +4 -0
  36. data/spec/motion/core/persistence_spec.rb +7 -3
  37. data/spec/motion/core/string_spec.rb +24 -0
  38. data/spec/motion/http_spec.rb +73 -61
  39. data/spec/motion/media/player_spec.rb +77 -0
  40. metadata +57 -14
@@ -117,8 +117,8 @@ module BubbleWrap
117
117
  if @retries > @options[:retries]
118
118
  error(Error::LOCATION_UNKNOWN)
119
119
  else
120
- self.locationManager.stopUpdatingLocation
121
- self.locationManager.startUpdatingLocation
120
+ self.location_manager.stopUpdatingLocation
121
+ self.location_manager.startUpdatingLocation
122
122
  end
123
123
  when KCLErrorNetwork
124
124
  error(Error::NETWORK_FAILURE)
@@ -0,0 +1,15 @@
1
+ module BubbleWrap
2
+ module Media
3
+ module_function
4
+
5
+ def play_modal(*args, &block)
6
+ Media::Player.new.retain.send(:play_modal, *args, &block)
7
+ end
8
+
9
+ def play(*args, &block)
10
+ Media::Player.new.retain.send(:play, *args, &block)
11
+ end
12
+ end
13
+ end
14
+
15
+ ::Media = BubbleWrap::Media
@@ -0,0 +1,139 @@
1
+ module BubbleWrap
2
+ module Media
3
+ module Error
4
+ class InvalidPlayerType < StandardError; end
5
+ class NilPlayerCallback < StandardError; end
6
+ end
7
+
8
+ class Player
9
+ attr_reader :media_player
10
+ ############
11
+ # Playing Media
12
+
13
+ # Plays media in the system-default modal controller
14
+ # Takes same parameters as #play
15
+ # NOTE: If you don't supply a :controller option,
16
+ # the rootViewController will be used.
17
+ def play_modal(content_url, options = {})
18
+ play(content_url, options.merge(modal: true))
19
+ end
20
+
21
+ # @param [String, NSURL] content_url is either a local or remote string
22
+ # for the location of the media you're playing.
23
+ # NOTE: if you're playing a remote file, your server needs to support
24
+ # range requests for that URL.
25
+ #
26
+ # @param [Hash] options to open the MPMoviePlayerController with
27
+ # the form {
28
+ # ### These are properties of MPMoviePlayerController
29
+ # allows_air_play: true/false; default false,
30
+ # control_style: [MPMovieControlStyle]; default MPMovieControlStyleDefault,
31
+ # end_playback_time: [Integer] end time (in seconds) for media; default is -1,
32
+ # initial_playback_time: [Integer] start time (in seconds) for media; default is -1,
33
+ # movie_source_type: [MPMovieSourceType] a "hint" so the player knows how to load the data type;
34
+ # either MPMovieSourceTypeFile or MPMovieSourceTypeStreaming; default is MPMovieSourceTypeUnknown
35
+ # which may delay playback,
36
+ # repeat_mode: [MPMovieRepeatMode] how the player repeats at the end of playback; defautl is
37
+ # MPMovieRepeatModeNone
38
+ # scaling_mode: [MPMovieScalingMode] scaling mode for movies; default is MPMovieScalingModeAspectFit
39
+ # should_autoplay: true/false; default true,
40
+ # use_application_audio_session: true/false; default true.
41
+ #
42
+ # ### These are properties of just the ::Player
43
+ # delay_play: true/false, default false. If false then you have to manually call
44
+ # @media_player.play in your code
45
+ # modal: true/false; default false,
46
+ # controller: [UIViewController] used to present the player modally;
47
+ # default uses root view controller of window
48
+ # }
49
+ #
50
+ # @block for when setup is done; use this block to present
51
+ # @media_player.view if options[:modal] == false
52
+ #
53
+ # EX
54
+ # From a local URL:
55
+ # file = File.join(App.resources_path, 'test.mp3')
56
+ # BW::Media::Player.play(NSURL.fileURLWithPath(file)) do |media_player|
57
+ # media_player.view.frame = some_view.bounds
58
+ # self.view.addSubview media_player.view
59
+ # end
60
+ #
61
+ # From a remote URL:
62
+ # BW::Media::Player.play("http://www.hrupin.com/wp-content/uploads/mp3/testsong_20_sec.mp3") do |media_player|
63
+ # media_player.view.frame = some_view.bounds
64
+ # self.view.addSubview media_player.view
65
+ # end
66
+ def play(content_url, options = {}, &block)
67
+ display_modal = !!options[:modal]
68
+
69
+ klass = display_modal ? MPMoviePlayerViewController : MPMoviePlayerController
70
+
71
+ content_url = content_url.is_a?(NSURL) ? content_url : NSURL.URLWithString(content_url)
72
+ @media_player = klass.alloc.initWithContentURL(content_url)
73
+
74
+ self.media_player.prepareToPlay if not display_modal
75
+
76
+ options[:delay_play] = false if not options.has_key? :delay_play
77
+ set_player_options(options)
78
+
79
+ NSNotificationCenter.defaultCenter.observe MPMoviePlayerPlaybackDidFinishNotification do |notification|
80
+ h = notification.userInfo
81
+ error = h["error"]
82
+ if error
83
+ p "BW::Media::Player error: #{error.userInfo.inspect}"
84
+ p "Code: #{error.code}, Domain: #{error.domain}"
85
+ end
86
+ end
87
+
88
+ if display_modal
89
+ @presenting_controller = options[:controller]
90
+ @presenting_controller ||= UIApplication.sharedApplication.keyWindow.rootViewController
91
+ @presenting_controller.presentMoviePlayerViewControllerAnimated(@media_player)
92
+ else
93
+ if block.nil?
94
+ raise Error::NilPlayerCallback, "no block callback given in #play; you need\
95
+ to supply one if options[:modal] == false"
96
+ end
97
+ block.call(@media_player)
98
+ end
99
+
100
+ if not display_modal and not options[:delay_play]
101
+ @media_player.play
102
+ end
103
+ end
104
+
105
+ # Stops playback for a Media::Player
106
+ def stop
107
+ if @media_player.is_a? MPMoviePlayerViewController
108
+ @presenting_controller.dismissMoviePlayerViewControllerAnimated
109
+ @presenting_controller = nil
110
+ else
111
+ @media_player.stop
112
+ end
113
+ @media_player = nil
114
+ end
115
+
116
+ def media_player
117
+ if @media_player.is_a? MPMoviePlayerViewController
118
+ return @media_player.moviePlayer
119
+ end
120
+ @media_player
121
+ end
122
+
123
+ private
124
+ # RubyMotion has a problem calling some objective-c methods at runtime, so we can't
125
+ # do any cool `camelize` tricks.
126
+ def set_player_options(options)
127
+ self.media_player.allowsAirPlay = options[:allows_air_play] if options.has_key? :allows_air_play
128
+ self.media_player.controlStyle = options[:control_style] if options.has_key? :control_style
129
+ self.media_player.endPlaybackTime = options[:end_playback_time] if options.has_key? :end_playback_time
130
+ self.media_player.initialPlaybackTime = options[:initial_playback_time] if options.has_key? :initial_playback_time
131
+ self.media_player.movieSourceType = options[:movie_source_type] if options.has_key? :movie_source_type
132
+ self.media_player.repeatMode = options[:repeat_mode] if options.has_key? :repeat_mode
133
+ self.media_player.scalingMode = options[:scaling_mode] if options.has_key? :scaling_mode
134
+ self.media_player.shouldAutoplay = options[:should_autoplay] if options.has_key? :should_autoplay
135
+ self.media_player.useApplicationAudioSession = options[:use_application_audio_session] if options.has_key? :use_application_audio_session
136
+ end
137
+ end
138
+ end
139
+ end
@@ -4,6 +4,7 @@ class TestSuiteDelegate
4
4
  def application(application, didFinishLaunchingWithOptions:launchOptions)
5
5
  @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
6
6
  @window.rootViewController = UIViewController.alloc.init
7
+ @window.makeKeyAndVisible
7
8
  true
8
9
  end
9
10
  end
Binary file
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gem 'bubble-wrap', '~> 1.1.0'
@@ -0,0 +1,4 @@
1
+ ## Location Demo
2
+
3
+ A bubble-wrap demo to show how to use location API.
4
+
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+ $:.unshift("/Library/RubyMotion/lib")
3
+ require 'motion/project'
4
+ require 'bubble-wrap/core'
5
+ require 'bubble-wrap/camera'
6
+
7
+ Motion::Project::App.setup do |app|
8
+ app.name = 'camera'
9
+ end
@@ -0,0 +1,8 @@
1
+ class AppDelegate
2
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
3
+ @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
4
+ camera_controller = CameraController.alloc.initWithNibName(nil, bundle:nil)
5
+ @window.rootViewController = camera_controller
6
+ @window.makeKeyAndVisible
7
+ end
8
+ end
@@ -0,0 +1,61 @@
1
+ class CameraController < UIViewController
2
+
3
+ def viewDidLoad
4
+ super
5
+
6
+ @buttons = []
7
+
8
+ @library = UIButton.buttonWithType(UIButtonTypeRoundedRect)
9
+ @library.setTitle("Library", forState:UIControlStateNormal)
10
+ @library.sizeToFit
11
+ @library.when UIControlEventTouchUpInside do
12
+ BW::Device.camera.any.picture(media_types: [:image]) do |result|
13
+ image_view = UIImageView.alloc.initWithImage(result[:original_image])
14
+ add_image_view(image_view)
15
+ end
16
+ end
17
+ self.view.addSubview(@library)
18
+ @buttons << @library
19
+
20
+ if BW::Device.camera.front?
21
+ @front = UIButton.buttonWithType(UIButtonTypeRoundedRect)
22
+ @front.setTitle("Front", forState:UIControlStateNormal)
23
+ @front.sizeToFit
24
+ last_button = @buttons.last
25
+ @front.frame = [[last_button.frame.origin.x, last_button.frame.origin.y + last_button.frame.size.height + 10], @front.frame.size]
26
+ @front.when UIControlEventTouchUpInside do
27
+ BW::Device.camera.front.picture(media_types: [:image]) do |result|
28
+ image_view = UIImageView.alloc.initWithImage(result[:original_image])
29
+ add_image_view(image_view)
30
+ end
31
+ end
32
+ self.view.addSubview(@front)
33
+ @buttons << @front
34
+ end
35
+
36
+ if BW::Device.camera.rear?
37
+ @rear = UIButton.buttonWithType(UIButtonTypeRoundedRect)
38
+ @rear.setTitle("Read", forState:UIControlStateNormal)
39
+ @rear.sizeToFit
40
+ last_button = @buttons.last
41
+ @rear.frame = [[last_button.frame.origin.x, last_button.frame.origin.y + last_button.frame.size.height + 10], @rear.frame.size]
42
+ @rear.when UIControlEventTouchUpInside do
43
+ BW::Device.camera.rear.picture(media_types: [:image]) do |result|
44
+ image_view = UIImageView.alloc.initWithImage(result[:original_image])
45
+ add_image_view(image_view)
46
+ end
47
+ end
48
+ self.view.addSubview(@rear)
49
+ @buttons << @rear
50
+ end
51
+ end
52
+
53
+ def add_image_view(image_view)
54
+ image_view.frame = [CGPointZero, self.view.frame.size]
55
+ image_view.center = [self.view.frame.size.width / 2, self.view.frame.size.height / 2]
56
+ self.view.addSubview(image_view)
57
+ @buttons.each do |button|
58
+ self.view.bringSubviewToFront(button)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,9 @@
1
+ describe "Application 'google_location'" do
2
+ before do
3
+ @app = UIApplication.sharedApplication
4
+ end
5
+
6
+ it "has one window" do
7
+ @app.windows.size.should == 1
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ .repl_history
2
+ build
3
+ resources/*.nib
4
+ resources/*.momd
5
+ resources/*.storyboardc
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gem 'bubble-wrap', '~> 1.1.0'
@@ -0,0 +1,4 @@
1
+ ## Location Demo
2
+
3
+ A bubble-wrap demo to show how to use location API.
4
+
@@ -0,0 +1,10 @@
1
+ # -*- coding: utf-8 -*-
2
+ $:.unshift("/Library/RubyMotion/lib")
3
+ require 'motion/project'
4
+ require 'bubble-wrap/location'
5
+ require 'bubble-wrap/http'
6
+ require 'bubble-wrap/core'
7
+
8
+ Motion::Project::App.setup do |app|
9
+ app.name = 'location'
10
+ end
@@ -0,0 +1,8 @@
1
+ class AppDelegate
2
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
3
+ @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
4
+ places_list_controller = PlacesListController.alloc.init
5
+ @window.rootViewController = places_list_controller
6
+ @window.makeKeyAndVisible
7
+ end
8
+ end
@@ -0,0 +1,30 @@
1
+ class PlacesListController < UITableViewController
2
+ attr_accessor :places_list
3
+
4
+ def viewDidLoad
5
+ @places_list = []
6
+ Places.load(self)
7
+ view.dataSource = view.delegate = self
8
+ end
9
+
10
+ def viewWillAppear(animated)
11
+ view.reloadData
12
+ end
13
+
14
+ def tableView(tableView, numberOfRowsInSection:section)
15
+ @places_list.size
16
+ end
17
+
18
+ def reloadData
19
+ view.reloadData
20
+ end
21
+
22
+ CellID = 'CellIdentifier'
23
+ def tableView(tableView, cellForRowAtIndexPath:indexPath)
24
+ cell = tableView.dequeueReusableCellWithIdentifier(CellID) || UITableViewCell.alloc.initWithStyle(UITableViewCellStyleSubtitle, reuseIdentifier:CellID)
25
+ placeItem= @places_list[indexPath.row]
26
+ cell.textLabel.text = placeItem
27
+ cell
28
+ end
29
+
30
+ end
@@ -0,0 +1,15 @@
1
+ class Places
2
+ API_KEY = ""
3
+ #See google places documentation at https://developers.google.com/places/documentation/ to obtain a key
4
+
5
+ def self.load(places_list_controller)
6
+ BW::Location.get do |result|
7
+ BW::Location.stop
8
+ BubbleWrap::HTTP.get("https://maps.googleapis.com/maps/api/place/search/json?location=#{result[:to].latitude},#{result[:to].longitude}&radius=500&sensor=false&key=#{API_KEY}") do |response|
9
+ names = BW::JSON.parse(response.body.to_str)["results"].map{|r| r["name"]}
10
+ places_list_controller.places_list = names
11
+ places_list_controller.reloadData
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ describe "Application 'google_location'" do
2
+ before do
3
+ @app = UIApplication.sharedApplication
4
+ end
5
+
6
+ it "has one window" do
7
+ @app.windows.size.should == 1
8
+ end
9
+ end
@@ -25,7 +25,7 @@ describe BubbleWrap::App do
25
25
 
26
26
  describe '.alert' do
27
27
  after do
28
- @alert.removeFromSuperview
28
+ @alert.dismissWithClickedButtonIndex(@alert.cancelButtonIndex, animated: false)
29
29
  end
30
30
 
31
31
  describe "with only one string argument" do
@@ -176,6 +176,12 @@ describe BubbleWrap::App do
176
176
  end
177
177
  end
178
178
 
179
+ describe '.app' do
180
+ it 'returns UIApplication.sharedApplication' do
181
+ BW::App.shared.should == UIApplication.sharedApplication
182
+ end
183
+ end
184
+
179
185
  describe '.run_after' do
180
186
  class DelayedRunAfterTest; attr_accessor :test_value end
181
187
 
@@ -32,6 +32,10 @@ EOS
32
32
  @parsed = BubbleWrap::JSON.parse(@json_string)
33
33
  end
34
34
 
35
+ it "doesn't crash when data is nil" do
36
+ Proc.new { BW::JSON.parse(nil) }.should.not.raise Exception
37
+ end
38
+
35
39
  it "should convert a top object into a Ruby hash" do
36
40
  obj = @parsed
37
41
  obj.class.should == Hash
@@ -1,7 +1,7 @@
1
1
  describe BubbleWrap::Persistence do
2
2
 
3
3
  describe '.app_key' do
4
-
4
+
5
5
  it "caches the @app_key" do
6
6
  BubbleWrap::Persistence.instance_variable_get(:@app_key).should.equal nil
7
7
  BubbleWrap::Persistence.app_key
@@ -21,7 +21,7 @@ describe BubbleWrap::Persistence do
21
21
  BubbleWrap::Persistence['arbitraryNumber'] = 42
22
22
  end.
23
23
  should.not.raise(Exception)
24
- end
24
+ end
25
25
 
26
26
  it "must call synchronize" do
27
27
  storage = NSUserDefaults.standardUserDefaults
@@ -29,7 +29,7 @@ describe BubbleWrap::Persistence do
29
29
 
30
30
  BubbleWrap::Persistence['arbitraryNumber'] = 42
31
31
  storage.instance_variable_get(:@sync_was_called).should.equal true
32
- end
32
+ end
33
33
  end
34
34
 
35
35
  describe "storing multiple objects" do
@@ -60,5 +60,9 @@ describe BubbleWrap::Persistence do
60
60
  BubbleWrap::Persistence['arbitraryNumber'].should == 42
61
61
  BubbleWrap::Persistence[:arbitraryString].should == 'test string'
62
62
  end
63
+
64
+ it 'returns fully functional strings' do
65
+ BubbleWrap::Persistence[:arbitraryString].methods.should == 'test string'.methods
66
+ end
63
67
  end
64
68
  end