bubble-wrap 1.1.3 → 1.1.4
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.
- data/CHANGELOG.md +17 -1
- data/Gemfile.lock +2 -2
- data/README.md +14 -13
- data/Rakefile +1 -0
- data/bubble-wrap.gemspec +2 -2
- data/lib/bubble-wrap/ext/motion_project_app.rb +1 -2
- data/lib/bubble-wrap/loader.rb +4 -1
- data/lib/bubble-wrap/rss_parser.rb +1 -0
- data/lib/bubble-wrap/version.rb +7 -1
- data/motion/core/app.rb +10 -1
- data/motion/core/device.rb +1 -1
- data/motion/core/device/camera.rb +5 -4
- data/motion/core/persistence.rb +1 -1
- data/motion/core/string.rb +12 -0
- data/motion/http.rb +11 -31
- data/motion/location/location.rb +1 -1
- data/motion/media/media.rb +1 -1
- data/motion/media/player.rb +1 -1
- data/motion/reactor.rb +1 -1
- data/motion/rss_parser.rb +24 -9
- data/motion/ui/gestures.rb +41 -8
- data/motion/ui/ui_control.rb +10 -3
- data/spec/lib/motion_stub.rb +1 -0
- data/spec/motion/core/app_spec.rb +22 -16
- data/spec/motion/core/gestures_spec.rb +12 -6
- data/spec/motion/core/string_spec.rb +42 -0
- data/spec/motion/core/ui_control_spec.rb +28 -8
- data/spec/motion/http_spec.rb +13 -0
- data/spec/motion/media/player_spec.rb +2 -2
- data/spec/motion/reactor_spec.rb +2 -2
- data/spec/motion/rss_parser_spec.rb +44 -11
- metadata +12 -4
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,22 @@
|
|
1
|
+
## Unreleased
|
2
|
+
|
3
|
+
[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.1.4...master)
|
4
|
+
|
5
|
+
## 1.1.4 (Unreleased)
|
6
|
+
|
7
|
+
[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.1.3...v1.1.4)
|
8
|
+
|
9
|
+
* Support RubyMotion 1.24 or above (https://github.com/rubymotion/BubbleWrap/pull/143)
|
10
|
+
* Fixed a problem with `when` events not properly handling multiple targets per event. Now defaults to one target per event with an option to append multiple targets.
|
11
|
+
|
12
|
+
## 1.1.3
|
13
|
+
|
14
|
+
[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.1.2...v1.1.3)
|
15
|
+
|
16
|
+
|
1
17
|
## 1.1.2
|
2
18
|
|
3
|
-
[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.1.
|
19
|
+
[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.1.1...v1.1.2)
|
4
20
|
|
5
21
|
* Fixed a problem with the load path.
|
6
22
|
* Added `format:` to the HTTP wrapper with [5 supported formats supported](https://github.com/rubymotion/BubbleWrap/pull/109) that sets the content type accordingly.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bubble-wrap (1.1.
|
4
|
+
bubble-wrap (1.1.4)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -10,7 +10,7 @@ GEM
|
|
10
10
|
metaclass (0.0.1)
|
11
11
|
mocha (0.11.4)
|
12
12
|
metaclass (~> 0.0.1)
|
13
|
-
mocha-on-bacon (0.2.
|
13
|
+
mocha-on-bacon (0.2.1)
|
14
14
|
mocha (>= 0.9.8)
|
15
15
|
rake (0.9.2.2)
|
16
16
|
|
data/README.md
CHANGED
@@ -169,6 +169,7 @@ Other available methods:
|
|
169
169
|
* `App.frame`
|
170
170
|
* `App.delegate`
|
171
171
|
* `App.shared`
|
172
|
+
* `App.window`
|
172
173
|
* `App.current_locale`
|
173
174
|
|
174
175
|
|
@@ -226,7 +227,7 @@ end
|
|
226
227
|
|
227
228
|
### JSON
|
228
229
|
|
229
|
-
`
|
230
|
+
`BW::JSON` wraps `NSJSONSerialization` available in iOS5 and offers the same API as Ruby's JSON std lib.
|
230
231
|
|
231
232
|
```ruby
|
232
233
|
BW::JSON.generate({'foo => 1, 'bar' => [1,2,3], 'baz => 'awesome'})
|
@@ -399,7 +400,7 @@ end
|
|
399
400
|
|
400
401
|
## HTTP
|
401
402
|
|
402
|
-
`
|
403
|
+
`BW::HTTP` wraps `NSURLRequest`, `NSURLConnection` and friends to provide Ruby developers with a more familiar and easier to use API.
|
403
404
|
The API uses async calls and blocks to stay as simple as possible.
|
404
405
|
|
405
406
|
To enable it add the following require line to your `Rakefile`:
|
@@ -410,22 +411,22 @@ require 'bubble-wrap/http'
|
|
410
411
|
Usage example:
|
411
412
|
|
412
413
|
```ruby
|
413
|
-
|
414
|
+
BW::HTTP.get("https://api.github.com/users/mattetti") do |response|
|
414
415
|
p response.body.to_str
|
415
416
|
end
|
416
417
|
```
|
417
418
|
|
418
419
|
```ruby
|
419
|
-
|
420
|
+
BW::HTTP.get("https://api.github.com/users/mattetti", {credentials: {username: 'matt', password: 'aimonetti'}}) do |response|
|
420
421
|
p response.body.to_str # prints the response's body
|
421
422
|
end
|
422
423
|
```
|
423
424
|
|
424
425
|
```ruby
|
425
426
|
data = {first_name: 'Matt', last_name: 'Aimonetti'}
|
426
|
-
|
427
|
+
BW::HTTP.post("http://foo.bar.com/", {payload: data}) do |response|
|
427
428
|
if response.ok?
|
428
|
-
json =
|
429
|
+
json = BW::JSON.parse(response.body.to_str)
|
429
430
|
p json['id']
|
430
431
|
elsif response.status_code.to_s =~ /40\d/
|
431
432
|
App.alert("Login failed")
|
@@ -520,9 +521,9 @@ feed_parser = BW::RSSParser.new(feed, true)
|
|
520
521
|
## Reactor
|
521
522
|
**Since: > version 1.0.0**
|
522
523
|
|
523
|
-
`
|
524
|
+
`BW::Reactor` is a simplified, mostly complete implementation of
|
524
525
|
the [Event Machine](http://rubyeventmachine.com/) API. In fact
|
525
|
-
`
|
526
|
+
`BW::Reactor` is aliased to `EM` in the runtime environment.
|
526
527
|
|
527
528
|
### Deferables
|
528
529
|
|
@@ -539,7 +540,7 @@ changes to either successful or failure state.
|
|
539
540
|
|
540
541
|
```ruby
|
541
542
|
> d = EM::DefaultDeferrable.new
|
542
|
-
=> #<
|
543
|
+
=> #<BW::Reactor::DefaultDeferrable:0x6d859a0>
|
543
544
|
> d.callback { |what| puts "Great #{what}!" }
|
544
545
|
=> [#<Proc:0x6d8a1e0>]
|
545
546
|
> d.succeed "justice"
|
@@ -551,7 +552,7 @@ Great justice!
|
|
551
552
|
|
552
553
|
```ruby
|
553
554
|
> d = EM::DefaultDeferrable.new
|
554
|
-
=> #<
|
555
|
+
=> #<BW::Reactor::DefaultDeferrable:0x8bf3ee0>
|
555
556
|
> d.errback { |what| puts "Great #{what}!" }
|
556
557
|
=> [#<Proc:0x8bf3ef0>]
|
557
558
|
> d.fail "sadness"
|
@@ -563,11 +564,11 @@ Great sadness!
|
|
563
564
|
|
564
565
|
```ruby
|
565
566
|
> d = EM::DefaultDeferrable.new
|
566
|
-
=> #<
|
567
|
+
=> #<BW::Reactor::DefaultDeferrable:0x8bf5910>
|
567
568
|
> d.errback { puts "Great scott!" }
|
568
569
|
=> [#<Proc:0x8bf6350>]
|
569
570
|
> d.timeout 2
|
570
|
-
=> #<
|
571
|
+
=> #<BW::Reactor::Timer:0x6d920a0 @timer=#<__NSCFTimer:0x6d91990>>
|
571
572
|
# wait...
|
572
573
|
> Great scott!
|
573
574
|
```
|
@@ -649,7 +650,7 @@ Time travel!
|
|
649
650
|
|
650
651
|
Although not part of the EventMachine API, BubbleWrap provides
|
651
652
|
an `Eventable` mixin for use instrumenting objects with simple
|
652
|
-
event triggering behaviour. `
|
653
|
+
event triggering behaviour. `BW::Reactor` uses this
|
653
654
|
behind the scenes in several places, and as it's a very handy
|
654
655
|
idiom it is available as a public API.
|
655
656
|
|
data/Rakefile
CHANGED
data/bubble-wrap.gemspec
CHANGED
@@ -2,8 +2,8 @@
|
|
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"]
|
6
|
-
gem.email = ["mattaimonetti@gmail.com", "francis@ignition.hk", "james@sociable.co.nz"]
|
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
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
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
9
|
gem.homepage = "http://bubblewrap.io/"
|
@@ -11,8 +11,7 @@ module BubbleWrap
|
|
11
11
|
app.frameworks = ::BubbleWrap::Requirement.frameworks(app.frameworks)
|
12
12
|
block.call(app) unless block.nil?
|
13
13
|
end
|
14
|
-
|
15
|
-
config.validate
|
14
|
+
config.setup_blocks << bw_config
|
16
15
|
end
|
17
16
|
alias :setup_without_bubblewrap :setup
|
18
17
|
alias :setup :setup_with_bubblewrap
|
data/lib/bubble-wrap/loader.rb
CHANGED
@@ -3,8 +3,11 @@ unless defined?(Motion::Project::Config)
|
|
3
3
|
end
|
4
4
|
|
5
5
|
unless defined?(BubbleWrap::LOADER_PRESENT)
|
6
|
-
|
7
6
|
require 'bubble-wrap/version' unless defined?(VERSION)
|
7
|
+
if BubbleWrap::minor_version(Motion::Version) < BubbleWrap::minor_version(BubbleWrap::MIN_MOTION_VERSION)
|
8
|
+
raise "BubbleWrap #{BubbleWrap::VERSION} requires at least rubymotion #{BubbleWrap::MIN_MOTION_VERSION}"
|
9
|
+
end
|
10
|
+
|
8
11
|
require 'bubble-wrap/ext'
|
9
12
|
require 'bubble-wrap/requirement'
|
10
13
|
|
data/lib/bubble-wrap/version.rb
CHANGED
data/motion/core/app.rb
CHANGED
@@ -90,6 +90,10 @@ module BubbleWrap
|
|
90
90
|
NSBundle.mainBundle.bundleIdentifier
|
91
91
|
end
|
92
92
|
|
93
|
+
def version
|
94
|
+
NSBundle.mainBundle.infoDictionary['CFBundleVersion']
|
95
|
+
end
|
96
|
+
|
93
97
|
# Return application frame
|
94
98
|
def frame
|
95
99
|
UIScreen.mainScreen.applicationFrame
|
@@ -110,6 +114,11 @@ module BubbleWrap
|
|
110
114
|
UIApplication.sharedApplication
|
111
115
|
end
|
112
116
|
|
117
|
+
# the Application Window
|
118
|
+
def window
|
119
|
+
UIApplication.sharedApplication.keyWindow || UIApplication.sharedApplication.windows[0]
|
120
|
+
end
|
121
|
+
|
113
122
|
# @return [NSLocale] locale of user settings
|
114
123
|
def current_locale
|
115
124
|
languages = NSLocale.preferredLanguages
|
@@ -122,4 +131,4 @@ module BubbleWrap
|
|
122
131
|
|
123
132
|
end
|
124
133
|
end
|
125
|
-
::App = BubbleWrap::App
|
134
|
+
::App = BubbleWrap::App unless defined?(::App)
|
data/motion/core/device.rb
CHANGED
@@ -87,6 +87,7 @@ module BubbleWrap
|
|
87
87
|
@options[:source_type] = :camera
|
88
88
|
end
|
89
89
|
|
90
|
+
source_type_readable = options[:source_type]
|
90
91
|
source_type = const_int_get("UIImagePickerControllerSourceType", @options[:source_type])
|
91
92
|
if not Camera.source_type_available?(source_type)
|
92
93
|
error(Error::SOURCE_TYPE_NOT_AVAILABLE) and return
|
@@ -108,15 +109,15 @@ module BubbleWrap
|
|
108
109
|
self.picker.mediaTypes = media_types
|
109
110
|
self.picker.allowsEditing = @options[:allows_editing]
|
110
111
|
|
111
|
-
if
|
112
|
+
if source_type_readable == :camera && ![:front, :rear].member?(self.location)
|
112
113
|
raise Error::INVALID_CAMERA_LOCATION, "Can't use camera location #{self.location} with source type :camera"
|
113
114
|
end
|
114
115
|
|
115
|
-
if
|
116
|
+
if source_type_readable == :camera
|
116
117
|
self.picker.cameraDevice = camera_device
|
117
118
|
end
|
118
119
|
|
119
|
-
presenting_controller ||=
|
120
|
+
presenting_controller ||= App.window.rootViewController
|
120
121
|
presenting_controller.presentViewController(self.picker, animated:@options[:animated], completion: lambda {})
|
121
122
|
end
|
122
123
|
|
@@ -216,4 +217,4 @@ module BubbleWrap
|
|
216
217
|
end
|
217
218
|
end
|
218
219
|
end
|
219
|
-
::Camera = BubbleWrap::Device::Camera
|
220
|
+
::Camera = BubbleWrap::Device::Camera unless defined?(::Camera)
|
data/motion/core/persistence.rb
CHANGED
data/motion/core/string.rb
CHANGED
@@ -33,6 +33,18 @@ module BubbleWrap
|
|
33
33
|
word
|
34
34
|
end
|
35
35
|
|
36
|
+
def to_url_encoded(encoding = NSUTF8StringEncoding)
|
37
|
+
stringByAddingPercentEscapesUsingEncoding encoding
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_url_decoded(encoding = NSUTF8StringEncoding)
|
41
|
+
stringByReplacingPercentEscapesUsingEncoding encoding
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_encoded_data(encoding = NSUTF8StringEncoding)
|
45
|
+
dataUsingEncoding encoding
|
46
|
+
end
|
47
|
+
|
36
48
|
def to_color
|
37
49
|
# First check if it is a color keyword
|
38
50
|
keyword_selector = "#{self.camelize(:lower)}Color"
|
data/motion/http.rb
CHANGED
@@ -18,45 +18,21 @@ module BubbleWrap
|
|
18
18
|
# p response.body.to_str # prints the response's body
|
19
19
|
# end
|
20
20
|
#
|
21
|
-
def self.get(url, options={}, &block)
|
22
|
-
create_query(url, :get, options, block)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Make a POST request
|
26
|
-
def self.post(url, options={}, &block)
|
27
|
-
create_query(url, :post, options, block)
|
28
|
-
end
|
29
21
|
|
30
|
-
|
31
|
-
def self.put(url, options={}, &block)
|
32
|
-
create_query(url, :put, options, block)
|
33
|
-
end
|
34
|
-
|
35
|
-
# Make a DELETE request
|
36
|
-
def self.delete(url, options={}, &block)
|
37
|
-
create_query(url, :delete, options, block)
|
38
|
-
end
|
22
|
+
[:get, :post, :put, :delete, :head, :patch].each do |http_verb|
|
39
23
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
# Make a PATCH request
|
46
|
-
def self.patch(url, options={}, &block)
|
47
|
-
create_query(url, :patch, options, block)
|
48
|
-
end
|
24
|
+
define_singleton_method(http_verb) do |url, options = {}, &block|
|
25
|
+
options[:action] = block if block
|
26
|
+
HTTP::Query.new(url, http_verb, options)
|
27
|
+
end
|
49
28
|
|
50
|
-
def self.create_query(url, method, options, block)
|
51
|
-
options[:action] = block if block
|
52
|
-
HTTP::Query.new(url, method, options)
|
53
29
|
end
|
54
30
|
|
55
31
|
# Response class wrapping the results of a Query's response
|
56
32
|
class Response
|
57
33
|
attr_reader :body
|
58
34
|
attr_reader :headers
|
59
|
-
attr_accessor :status_code, :error_message
|
35
|
+
attr_accessor :status_code, :status_description, :error_message
|
60
36
|
attr_reader :url
|
61
37
|
|
62
38
|
def initialize(values={})
|
@@ -67,6 +43,7 @@ module BubbleWrap
|
|
67
43
|
values.each do |k,v|
|
68
44
|
self.instance_variable_set("@#{k}", v)
|
69
45
|
end
|
46
|
+
update_status_description
|
70
47
|
end
|
71
48
|
|
72
49
|
def ok?
|
@@ -78,6 +55,9 @@ module BubbleWrap
|
|
78
55
|
end
|
79
56
|
alias description to_s
|
80
57
|
|
58
|
+
def update_status_description
|
59
|
+
@status_description = status_code.nil? ? nil : NSHTTPURLResponse.localizedStringForStatusCode(status_code)
|
60
|
+
end
|
81
61
|
end
|
82
62
|
|
83
63
|
# Class wrapping NSConnection and often used indirectly by the BubbleWrap::HTTP module methods.
|
@@ -356,7 +336,7 @@ Cache policy: #{@cache_policy}, response: #{@response.inspect} >"
|
|
356
336
|
return nil if hash.nil?
|
357
337
|
escaped_hash = {}
|
358
338
|
|
359
|
-
hash.each{|k,v| escaped_hash[k] = v.gsub("\n", CLRF) }
|
339
|
+
hash.each{|k,v| escaped_hash[k] = v.gsub("\n", CLRF) if v }
|
360
340
|
escaped_hash
|
361
341
|
end
|
362
342
|
|
data/motion/location/location.rb
CHANGED
data/motion/media/media.rb
CHANGED
data/motion/media/player.rb
CHANGED
@@ -87,7 +87,7 @@ module BubbleWrap
|
|
87
87
|
|
88
88
|
if display_modal
|
89
89
|
@presenting_controller = options[:controller]
|
90
|
-
@presenting_controller ||=
|
90
|
+
@presenting_controller ||= App.window.rootViewController
|
91
91
|
@presenting_controller.presentMoviePlayerViewControllerAnimated(@media_player)
|
92
92
|
else
|
93
93
|
if block.nil?
|
data/motion/reactor.rb
CHANGED
data/motion/rss_parser.rb
CHANGED
@@ -50,19 +50,16 @@ module BubbleWrap
|
|
50
50
|
if data
|
51
51
|
data_to_parse = input.respond_to?(:to_data) ? input.to_data : input
|
52
52
|
@source = data_to_parse
|
53
|
-
@parser = NSXMLParser.alloc.initWithData(@source)
|
54
53
|
else
|
55
54
|
url = input.is_a?(NSURL) ? input : NSURL.alloc.initWithString(input)
|
56
55
|
@source = url
|
57
|
-
# Delay the initialization of the underlying NSXMLParser so it
|
58
|
-
# doesn't load the content of the url until it's triggered.
|
59
|
-
@parser = Proc.new{ NSXMLParser.alloc.initWithContentsOfURL(url) }
|
60
56
|
end
|
61
57
|
self.state = :initializes
|
62
58
|
self
|
63
59
|
end
|
64
60
|
|
65
61
|
def state=(new_state)
|
62
|
+
@state = new_state
|
66
63
|
callback_meth = "when_parser_#{new_state}"
|
67
64
|
if self.delegate && self.delegate.respond_to?(callback_meth)
|
68
65
|
self.delegate.send(callback_meth)
|
@@ -77,10 +74,13 @@ module BubbleWrap
|
|
77
74
|
# end
|
78
75
|
def parse(&block)
|
79
76
|
@block = block
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
77
|
+
|
78
|
+
fetch_source_data do |data|
|
79
|
+
@parser = NSXMLParser.alloc.initWithData(data)
|
80
|
+
@parser.shouldProcessNamespaces = true
|
81
|
+
@parser.delegate ||= self
|
82
|
+
@parser.parse
|
83
|
+
end
|
84
84
|
end
|
85
85
|
|
86
86
|
# Delegate getting called when parsing starts
|
@@ -120,7 +120,7 @@ module BubbleWrap
|
|
120
120
|
# error can be retrieved with parserError
|
121
121
|
def parser(parser, parseErrorOccurred:parse_error)
|
122
122
|
puts "parseErrorOccurred" if debug
|
123
|
-
@
|
123
|
+
@parser_error = parse_error
|
124
124
|
|
125
125
|
self.state = :errors
|
126
126
|
end
|
@@ -140,5 +140,20 @@ module BubbleWrap
|
|
140
140
|
# parser:validationErrorOccurred:
|
141
141
|
# parser:foundCDATA:
|
142
142
|
|
143
|
+
protected
|
144
|
+
|
145
|
+
def fetch_source_data(&blk)
|
146
|
+
if @source.is_a?(NSURL)
|
147
|
+
HTTP.get(@source.absoluteString) do |response|
|
148
|
+
if response.ok?
|
149
|
+
blk.call(response.body)
|
150
|
+
else
|
151
|
+
parser(parser, parseErrorOccurred:"HTTP request failed (#{response})")
|
152
|
+
end
|
153
|
+
end
|
154
|
+
else
|
155
|
+
yield @source
|
156
|
+
end
|
157
|
+
end
|
143
158
|
end
|
144
159
|
end
|
data/motion/ui/gestures.rb
CHANGED
@@ -2,38 +2,71 @@
|
|
2
2
|
|
3
3
|
class UIView
|
4
4
|
|
5
|
+
def when_tapped(enableInteraction=true, &proc)
|
6
|
+
add_gesture_recognizer_helper(UITapGestureRecognizer.alloc.initWithTarget(self, action:'handle_gesture:'), enableInteraction, proc)
|
7
|
+
end
|
8
|
+
|
9
|
+
def when_pinched(enableInteraction=true, &proc)
|
10
|
+
add_gesture_recognizer_helper(UIPinchGestureRecognizer.alloc.initWithTarget(self, action:'handle_gesture:'), enableInteraction, proc)
|
11
|
+
end
|
12
|
+
|
13
|
+
def when_rotated(enableInteraction=true, &proc)
|
14
|
+
add_gesture_recognizer_helper(UIRotationGestureRecognizer.alloc.initWithTarget(self, action:'handle_gesture:'), enableInteraction, proc)
|
15
|
+
end
|
16
|
+
|
17
|
+
def when_swiped(enableInteraction=true, &proc)
|
18
|
+
add_gesture_recognizer_helper(UISwipeGestureRecognizer.alloc.initWithTarget(self, action:'handle_gesture:'), enableInteraction, proc)
|
19
|
+
end
|
20
|
+
|
21
|
+
def when_panned(enableInteraction=true, &proc)
|
22
|
+
add_gesture_recognizer_helper(UIPanGestureRecognizer.alloc.initWithTarget(self, action:'handle_gesture:'), enableInteraction, proc)
|
23
|
+
end
|
24
|
+
|
25
|
+
def when_pressed(enableInteraction=true, &proc)
|
26
|
+
add_gesture_recognizer_helper(UILongPressGestureRecognizer.alloc.initWithTarget(self, action:'handle_gesture:'), enableInteraction, proc)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
5
30
|
def whenTapped(enableInteraction=true, &proc)
|
6
|
-
|
31
|
+
NSLog "[DEPRECATED - whenTapped] please use when_tapped instead."
|
32
|
+
when_tapped(enableInteraction, &proc)
|
7
33
|
end
|
8
34
|
|
9
35
|
def whenPinched(enableInteraction=true, &proc)
|
10
|
-
|
36
|
+
NSLog "[DEPRECATED - whenPinched] please use when_pinched instead."
|
37
|
+
when_pinched(enableInteraction, &proc)
|
11
38
|
end
|
12
39
|
|
13
40
|
def whenRotated(enableInteraction=true, &proc)
|
14
|
-
|
41
|
+
NSLog "[DEPRECATED - whenRotated] please use when_rotated instead."
|
42
|
+
when_rotated(enableInteraction, &proc)
|
15
43
|
end
|
16
44
|
|
17
45
|
def whenSwiped(enableInteraction=true, &proc)
|
18
|
-
|
46
|
+
NSLog "[DEPRECATED - whenSwiped] please use when_swiped instead."
|
47
|
+
when_swiped(enableInteraction, &proc)
|
19
48
|
end
|
20
49
|
|
21
50
|
def whenPanned(enableInteraction=true, &proc)
|
22
|
-
|
51
|
+
NSLog "[DEPRECATED - whenPanned] please use when_panned instead."
|
52
|
+
when_panned(enableInteraction, &proc)
|
23
53
|
end
|
24
54
|
|
25
55
|
def whenPressed(enableInteraction=true, &proc)
|
26
|
-
|
56
|
+
NSLog "[DEPRECATED - whenPressed] please use when_pressed instead."
|
57
|
+
when_pressed(enableInteraction, &proc)
|
27
58
|
end
|
28
59
|
|
60
|
+
|
61
|
+
|
29
62
|
private
|
30
63
|
|
31
|
-
def
|
64
|
+
def handle_gesture(recognizer)
|
32
65
|
@recognizers[recognizer].call(recognizer)
|
33
66
|
end
|
34
67
|
|
35
68
|
# Adds the recognizer and keeps a strong reference to the Proc object.
|
36
|
-
def
|
69
|
+
def add_gesture_recognizer_helper(recognizer, enableInteraction, proc)
|
37
70
|
setUserInteractionEnabled true if enableInteraction && !isUserInteractionEnabled
|
38
71
|
self.addGestureRecognizer(recognizer)
|
39
72
|
|
data/motion/ui/ui_control.rb
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
module UIControlWrap
|
2
|
-
def when(events, &block)
|
2
|
+
def when(events, options={}, &block)
|
3
3
|
@callback ||= {}
|
4
|
-
@callback[events]
|
5
|
-
|
4
|
+
@callback[events] ||= []
|
5
|
+
|
6
|
+
unless options[:append]
|
7
|
+
@callback[events] = []
|
8
|
+
removeTarget(nil, action: nil, forControlEvents: events)
|
9
|
+
end
|
10
|
+
|
11
|
+
@callback[events] << block
|
12
|
+
addTarget(@callback[events].last, action:'call', forControlEvents: events)
|
6
13
|
end
|
7
14
|
end
|
data/spec/lib/motion_stub.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
1
|
describe BubbleWrap::App do
|
2
2
|
describe '.documents_path' do
|
3
3
|
it 'should end in "/Documents"' do
|
4
|
-
|
4
|
+
App.documents_path[-10..-1].should == '/Documents'
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
8
|
describe '.resources_path' do
|
9
9
|
it 'should end in "/testSuite.app"' do
|
10
|
-
|
10
|
+
App.resources_path.should =~ /\/testSuite(_spec)?.app$/
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
describe '.notification_center' do
|
15
15
|
it 'should be a NSNotificationCenter' do
|
16
|
-
|
16
|
+
App.notification_center.should == NSNotificationCenter.defaultCenter
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
describe '.user_cache' do
|
21
21
|
it 'should be a NSUserDefaults' do
|
22
|
-
|
22
|
+
App.user_cache.should == NSUserDefaults.standardUserDefaults
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -30,7 +30,7 @@ describe BubbleWrap::App do
|
|
30
30
|
|
31
31
|
describe "with only one string argument" do
|
32
32
|
before do
|
33
|
-
@alert =
|
33
|
+
@alert = App.alert('1.21 Gigawatts!')
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'returns an alert' do
|
@@ -54,7 +54,7 @@ describe BubbleWrap::App do
|
|
54
54
|
|
55
55
|
describe "with only two string arguments" do
|
56
56
|
before do
|
57
|
-
@alert =
|
57
|
+
@alert = App.alert('1.21 Gigawatts!', 'Great Scott!')
|
58
58
|
end
|
59
59
|
|
60
60
|
it 'returns an alert' do
|
@@ -78,7 +78,7 @@ describe BubbleWrap::App do
|
|
78
78
|
|
79
79
|
describe "with variable args" do
|
80
80
|
before do
|
81
|
-
@alert =
|
81
|
+
@alert = App.alert('1.21 Gigawatts!', cancel_button_title: 'Great Scott!',
|
82
82
|
message: 'Some random message')
|
83
83
|
end
|
84
84
|
|
@@ -107,7 +107,7 @@ describe BubbleWrap::App do
|
|
107
107
|
|
108
108
|
describe "with a block" do
|
109
109
|
before do
|
110
|
-
@alert =
|
110
|
+
@alert = App.alert('1.21 Gigawatts!') do |alert|
|
111
111
|
alert.message = 'My message!!'
|
112
112
|
end
|
113
113
|
end
|
@@ -138,47 +138,53 @@ describe BubbleWrap::App do
|
|
138
138
|
|
139
139
|
describe '.states' do
|
140
140
|
it 'returns a hash' do
|
141
|
-
|
141
|
+
App.states.class.should == Hash
|
142
142
|
end
|
143
143
|
it "returns the real instance variable" do
|
144
|
-
|
144
|
+
App.states.should == App.instance_variable_get(:@states)
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
148
148
|
describe '.name' do
|
149
149
|
it 'returns the application name' do
|
150
|
-
|
150
|
+
App.name.should == 'testSuite'
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
154
|
describe '.identifier' do
|
155
155
|
it 'returns the application identifier' do
|
156
|
-
|
156
|
+
App.identifier.should == 'io.bubblewrap.testSuite_spec'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe '.version' do
|
161
|
+
it 'returns the application version' do
|
162
|
+
App.version.should == '1.2.3'
|
157
163
|
end
|
158
164
|
end
|
159
165
|
|
160
166
|
describe '.frame' do
|
161
167
|
it 'returns Application Frame' do
|
162
|
-
|
168
|
+
App.frame.should == UIScreen.mainScreen.applicationFrame
|
163
169
|
end
|
164
170
|
end
|
165
171
|
|
166
172
|
describe '.bounds' do
|
167
173
|
it 'returns Main Screen bounds' do
|
168
|
-
|
174
|
+
App.bounds.should == UIScreen.mainScreen.bounds
|
169
175
|
end
|
170
176
|
end
|
171
177
|
|
172
178
|
|
173
179
|
describe '.delegate' do
|
174
180
|
it 'returns a TestSuiteDelegate' do
|
175
|
-
|
181
|
+
App.delegate.should == UIApplication.sharedApplication.delegate
|
176
182
|
end
|
177
183
|
end
|
178
184
|
|
179
185
|
describe '.app' do
|
180
186
|
it 'returns UIApplication.sharedApplication' do
|
181
|
-
|
187
|
+
App.shared.should == UIApplication.sharedApplication
|
182
188
|
end
|
183
189
|
end
|
184
190
|
|
@@ -29,27 +29,33 @@ describe UIView do
|
|
29
29
|
# it 'responds to interaction'
|
30
30
|
end
|
31
31
|
|
32
|
-
describe '#
|
32
|
+
describe '#when_tapped' do
|
33
|
+
testMethod.call :when_tapped
|
33
34
|
testMethod.call :whenTapped
|
34
35
|
end
|
35
36
|
|
36
|
-
describe '#
|
37
|
+
describe '#when_pinched' do
|
38
|
+
testMethod.call :when_pinched
|
37
39
|
testMethod.call :whenPinched
|
38
40
|
end
|
39
41
|
|
40
|
-
describe '#
|
42
|
+
describe '#when_rotated' do
|
43
|
+
testMethod.call :when_rotated
|
41
44
|
testMethod.call :whenRotated
|
42
45
|
end
|
43
46
|
|
44
|
-
describe '#
|
47
|
+
describe '#when_swiped' do
|
48
|
+
testMethod.call :when_swiped
|
45
49
|
testMethod.call :whenSwiped
|
46
50
|
end
|
47
51
|
|
48
|
-
describe '#
|
52
|
+
describe '#when_panned' do
|
53
|
+
testMethod.call :when_panned
|
49
54
|
testMethod.call :whenPanned
|
50
55
|
end
|
51
56
|
|
52
|
-
describe '#
|
57
|
+
describe '#when_pressed' do
|
58
|
+
testMethod.call :when_pressed
|
53
59
|
testMethod.call :whenPressed
|
54
60
|
end
|
55
61
|
|
@@ -143,4 +143,46 @@ describe BubbleWrap::String do
|
|
143
143
|
end
|
144
144
|
|
145
145
|
end
|
146
|
+
|
147
|
+
describe "encoding" do
|
148
|
+
|
149
|
+
before do
|
150
|
+
@raw_string = "hey ho let's {go}"
|
151
|
+
end
|
152
|
+
|
153
|
+
it "to_url_encoded" do
|
154
|
+
real_encoded = @raw_string.stringByAddingPercentEscapesUsingEncoding NSUTF8StringEncoding
|
155
|
+
@raw_string.to_url_encoded.should.equal real_encoded
|
156
|
+
end
|
157
|
+
|
158
|
+
it "handles other encodings" do
|
159
|
+
utf16 = @raw_string.stringByAddingPercentEscapesUsingEncoding NSUTF16StringEncoding
|
160
|
+
@raw_string.to_url_encoded(NSUTF16StringEncoding).should.equal utf16
|
161
|
+
end
|
162
|
+
|
163
|
+
it "to_url_decoded" do
|
164
|
+
encoded_string = "hey%20ho%20let's%20%7Bgo%7D"
|
165
|
+
real_decoded = encoded_string.stringByReplacingPercentEscapesUsingEncoding NSUTF8StringEncoding
|
166
|
+
|
167
|
+
encoded_string.to_url_decoded.should.equal real_decoded
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
describe "dataUsingEncoding" do
|
172
|
+
|
173
|
+
it "#to_url_encoded_data - utf8" do
|
174
|
+
utf8 = @raw_string.dataUsingEncoding NSUTF8StringEncoding
|
175
|
+
@raw_string.to_encoded_data.should.equal utf8
|
176
|
+
end
|
177
|
+
|
178
|
+
it "handles multiple encodings" do
|
179
|
+
utf16 = @raw_string.dataUsingEncoding NSUTF16StringEncoding
|
180
|
+
@raw_string.to_encoded_data(NSUTF16StringEncoding).should.equal utf16
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
end
|
187
|
+
|
146
188
|
end
|
@@ -1,16 +1,36 @@
|
|
1
1
|
describe "UIControlWrap" do
|
2
|
+
describe 'UIButton' do
|
3
|
+
before do
|
4
|
+
@button = UIButton.buttonWithType(UIButtonTypeRoundedRect)
|
5
|
+
@touched = []
|
6
|
+
@button.when(UIControlEventTouchUpInside) do
|
7
|
+
@touched << 'for the very first time'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "supports the 'when' event handler for UIButton" do
|
12
|
+
@button.sendActionsForControlEvents(UIControlEventTouchUpInside)
|
13
|
+
@touched.should == ['for the very first time']
|
14
|
+
end
|
15
|
+
|
16
|
+
it "replaces the target for a given control event by default" do
|
17
|
+
@button.when(UIControlEventTouchUpInside) do
|
18
|
+
@touched << 'touched'
|
19
|
+
end
|
20
|
+
@button.sendActionsForControlEvents(UIControlEventTouchUpInside)
|
21
|
+
@touched.should == ['touched']
|
22
|
+
end
|
2
23
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
24
|
+
it "allows multiple targets for a given control event if specified" do
|
25
|
+
@button.when(UIControlEventTouchUpInside, append: true) do
|
26
|
+
@touched << 'touched'
|
27
|
+
end
|
28
|
+
@button.sendActionsForControlEvents(UIControlEventTouchUpInside)
|
29
|
+
@touched.should == ['for the very first time', 'touched']
|
8
30
|
end
|
9
|
-
button.sendActionsForControlEvents(UIControlEventTouchUpInside)
|
10
|
-
touched.should == 'for the very first time'
|
11
31
|
end
|
12
32
|
|
13
|
-
it "
|
33
|
+
it "supports the 'when' event handler for UISlider" do
|
14
34
|
button = UISlider.alloc.init
|
15
35
|
changed = nil
|
16
36
|
button.when(UIControlEventValueChanged) do
|
data/spec/motion/http_spec.rb
CHANGED
@@ -75,6 +75,10 @@ describe "HTTP" do
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
it "updates the status description" do
|
79
|
+
@response.status_description.should.equal 'no error'
|
80
|
+
end
|
81
|
+
|
78
82
|
it "updates ivars when calling update" do
|
79
83
|
@response.update(one: 'one', two: 'two')
|
80
84
|
@response.instance_variable_get(:@one).should.equal 'one'
|
@@ -143,6 +147,15 @@ describe "HTTP" do
|
|
143
147
|
@query.should.respond_to :options
|
144
148
|
end
|
145
149
|
|
150
|
+
it "should accept nil header value" do
|
151
|
+
@headers = { 'Authorization' => nil, 'User-Agent' => "Mozilla/5.0 (X11; Linux x86_64; rv:12.0) \n Gecko/20100101 Firefox/12.0" }
|
152
|
+
@options = {
|
153
|
+
headers: @headers,
|
154
|
+
}
|
155
|
+
@query = BubbleWrap::HTTP::Query.new( @localhost_url , :get, @options )
|
156
|
+
@query.should.not.be.nil
|
157
|
+
end
|
158
|
+
|
146
159
|
describe "When initialized" do
|
147
160
|
|
148
161
|
it "should upcase the HTTP method" do
|
@@ -36,7 +36,7 @@ describe BubbleWrap::Media::Player do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should present a modalViewController on root if no controller given" do
|
39
|
-
@controller =
|
39
|
+
@controller = App.window.rootViewController
|
40
40
|
|
41
41
|
@player.play_modal(@local_file)
|
42
42
|
|
@@ -58,7 +58,7 @@ describe BubbleWrap::Media::Player do
|
|
58
58
|
# .presentMoviePlayerViewControllerAnimated detects whether or not
|
59
59
|
# @controller.view is part of a hierarchy, I guess. if you remove this
|
60
60
|
# then the test fails.
|
61
|
-
|
61
|
+
App.window.rootViewController.view.addSubview(@controller.view)
|
62
62
|
|
63
63
|
@player.play_modal(@local_file, controller: @controller)
|
64
64
|
|
data/spec/motion/reactor_spec.rb
CHANGED
@@ -45,9 +45,9 @@ describe BubbleWrap::Reactor do
|
|
45
45
|
describe '.add_periodic_timer' do
|
46
46
|
it 'runs callbacks repeatedly' do
|
47
47
|
@proxy.proof = 0
|
48
|
-
timer = @subject.add_periodic_timer 0.5 do
|
48
|
+
@timer = @subject.add_periodic_timer 0.5 do
|
49
49
|
@proxy.proof = @proxy.proof + 1
|
50
|
-
@subject.cancel_timer(timer) if @proxy.proof > 2
|
50
|
+
@subject.cancel_timer(@timer) if @proxy.proof > 2
|
51
51
|
end
|
52
52
|
wait 1.1 do
|
53
53
|
@proxy.proof.should >= 2
|
@@ -19,18 +19,51 @@ describe "RSSParser" do
|
|
19
19
|
parser.source.class.should.equal NSURL
|
20
20
|
parser.source.absoluteString.should.equal @feed_url
|
21
21
|
end
|
22
|
-
|
23
|
-
# it "works with some data" do
|
24
|
-
# feed_data_string = File.read(@local_feed)
|
25
|
-
# parser = BW::RSSParser.new(feed_data_string, true)
|
26
|
-
# parser.source.class.should.equal NSData
|
27
|
-
# parser.source.to_str.should.equal @feed_data_string
|
28
|
-
# parser = BW::RSSParser.new(@feed_data_string.to_data, true)
|
29
|
-
# parser.source.class.should.equal NSURL
|
30
|
-
# parser.source.class.should.equal NSData
|
31
|
-
# parser.source.to_str.should.equal @feed_data_string
|
32
|
-
# end
|
33
22
|
end
|
34
23
|
|
24
|
+
describe "parsing" do
|
25
|
+
|
26
|
+
it "parses local file data" do
|
27
|
+
parser = BW::RSSParser.new(File.read(@local_feed).to_data, true)
|
28
|
+
episodes = []
|
29
|
+
parser.parse { |episode| episodes << episode }
|
30
|
+
episodes.length.should.equal 108
|
31
|
+
episodes.last.title.should.equal 'Episode 001: Summer of Rails'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "parses url data" do
|
35
|
+
parser = BW::RSSParser.new(@feed_url)
|
36
|
+
episodes = []
|
37
|
+
parser.parse { |episode| episodes << episode }
|
38
|
+
episodes.length.should.equal 108
|
39
|
+
episodes.last.title.should.equal 'Episode 001: Summer of Rails'
|
40
|
+
end
|
41
|
+
|
42
|
+
it "handles errors" do
|
43
|
+
parser = BW::RSSParser.new("http://doesnotexist.com")
|
44
|
+
parser.parse
|
45
|
+
parser.state.should.equal :errors
|
46
|
+
end
|
47
|
+
|
48
|
+
module BW
|
49
|
+
module HTTP
|
50
|
+
class << self
|
51
|
+
# To avoid interfering the http_spec's mocking, we only want to override HTTP.get if it's
|
52
|
+
# for the RSSParser spec.
|
53
|
+
alias_method :original_get, :get
|
54
|
+
def get(url, options={}, &block)
|
55
|
+
if url == 'https://raw.github.com/gist/2952427/9f1522cbe5d77a72c7c96c4fdb4b77bd58d7681e/atom.xml'
|
56
|
+
string = File.read(File.join(App.resources_path, 'atom.xml'))
|
57
|
+
yield BW::HTTP::Response.new(body: string.to_data, status_code: 200)
|
58
|
+
elsif url == 'http://doesnotexist.com'
|
59
|
+
yield BW::HTTP::Response.new(status_code: nil)
|
60
|
+
else
|
61
|
+
original_get(url, options, &block)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
35
68
|
end
|
36
69
|
|
metadata
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bubble-wrap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Matt Aimonetti
|
9
9
|
- Francis Chong
|
10
10
|
- James Harton
|
11
|
+
- Clay Allsopp
|
12
|
+
- Dylan Markow
|
13
|
+
- Jan Weinkauff
|
14
|
+
- Marin Usalj
|
11
15
|
autorequire:
|
12
16
|
bindir: bin
|
13
17
|
cert_chain: []
|
14
|
-
date: 2012-
|
18
|
+
date: 2012-09-26 00:00:00.000000000 Z
|
15
19
|
dependencies:
|
16
20
|
- !ruby/object:Gem::Dependency
|
17
21
|
name: mocha
|
@@ -83,6 +87,10 @@ email:
|
|
83
87
|
- mattaimonetti@gmail.com
|
84
88
|
- francis@ignition.hk
|
85
89
|
- james@sociable.co.nz
|
90
|
+
- clay.allsopp@gmail.com
|
91
|
+
- dylan@dylanmarkow.com
|
92
|
+
- jan@dreimannzelt.de
|
93
|
+
- mneorr@gmail.com
|
86
94
|
executables: []
|
87
95
|
extensions: []
|
88
96
|
extra_rdoc_files:
|
@@ -283,7 +291,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
283
291
|
version: '0'
|
284
292
|
segments:
|
285
293
|
- 0
|
286
|
-
hash:
|
294
|
+
hash: -27678325849561073
|
287
295
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
288
296
|
none: false
|
289
297
|
requirements:
|
@@ -292,7 +300,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
292
300
|
version: '0'
|
293
301
|
segments:
|
294
302
|
- 0
|
295
|
-
hash:
|
303
|
+
hash: -27678325849561073
|
296
304
|
requirements: []
|
297
305
|
rubyforge_project:
|
298
306
|
rubygems_version: 1.8.24
|