under-os 1.0.0 → 1.1.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/README.md +4 -12
- data/Rakefile +1 -0
- data/app/layouts/home.html +9 -10
- data/app/pages/collections_page.rb +6 -0
- data/app/pages/http_page.rb +9 -4
- data/app/styles/collections.css +4 -0
- data/lib/under-os.rb +2 -4
- data/lib/under_os/color.rb +18 -10
- data/lib/under_os/core/array.rb +5 -0
- data/lib/under_os/core/hash.rb +10 -0
- data/lib/under_os/core/json.rb +19 -0
- data/lib/under_os/core/object.rb +9 -0
- data/lib/under_os/core/string.rb +40 -0
- data/lib/under_os/file.rb +1 -1
- data/lib/under_os/http/cookies.rb +30 -0
- data/lib/under_os/http/request.rb +37 -20
- data/lib/under_os/http/response.rb +4 -0
- data/lib/under_os/http.rb +27 -1
- data/lib/under_os/ui/collection/delegate.rb +4 -2
- data/lib/under_os/ui/collection.rb +3 -1
- data/lib/under_os/ui/locker.rb +1 -1
- data/lib/under_os/ui/style/fonts.rb +18 -24
- data/lib/under_os/ui/style/margins.rb +34 -30
- data/lib/under_os.rb +1 -1
- data/spec/lib/core/hash_spec.rb +19 -0
- data/spec/lib/core/json_spec.rb +32 -0
- data/spec/lib/core/string_spec.rb +34 -0
- data/spec/lib/under_os/http/cookies_spec.rb +13 -0
- data/spec/lib/under_os/http/request_spec.rb +44 -0
- data/spec/lib/under_os/http_spec.rb +20 -0
- data/under-os.gemspec +4 -2
- metadata +38 -9
- data/app/pages/stuff_page.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ff1789b7dfe17082f36cf9eea7c8c3444077716
|
4
|
+
data.tar.gz: 520c56f69fdc975f55be7e49d87f3742c12e4dca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea4aab7ec336bd41cde899ab86f4caeaa9d206cb7261915eb85157b97a117b628b41e204df63627ac9e18f36e99e0cedc70f876d7441a6cee27bfbe74afb2aef
|
7
|
+
data.tar.gz: 3e7eee7f55f17c5952b96741f2db01cd7ea38e2842476eca515f27a3e093cb8c5516bef93f8dd51cfbd86be60c398d1f1e861540ed63e6283e4183ed41ff9e2c
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
# Under OS
|
1
|
+
# Under OS [](https://travis-ci.org/under-os/under-os) [](https://codeclimate.com/github/under-os/under-os)
|
2
2
|
|
3
|
-
|
3
|
+
[UnderOS](http://under-os.com) is an experiment in building a thin web-like wrapper over iOS using rubymotion
|
4
4
|
|
5
|
-
The idea is to use
|
5
|
+
The idea is to use encapsulation instead of monkey patching and build the
|
6
6
|
entire development platform correctly and from scratch.
|
7
7
|
|
8
|
-
The result should be a
|
8
|
+
The result should be a _webbish_ infrastructure that uses ruby instead
|
9
9
|
of JavaScript and compiles into native code in the end.
|
10
10
|
|
11
11
|
That's gonna be legendary!
|
@@ -37,14 +37,6 @@ Now, Run it!
|
|
37
37
|
cd test && rake
|
38
38
|
```
|
39
39
|
|
40
|
-
## What's What
|
41
|
-
|
42
|
-
* `app/layouts` - where you keep your HTML layouts
|
43
|
-
* `app/pages` - where the page scripts live
|
44
|
-
* `app/styles` - where the CSS files go
|
45
|
-
* `app/models` - where your data models chill
|
46
|
-
* `app/views` - where you keep your custom views/components classes
|
47
|
-
|
48
40
|
|
49
41
|
# Copyright & License
|
50
42
|
|
data/Rakefile
CHANGED
data/app/layouts/home.html
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
<page title="Home">
|
2
2
|
<view id="buttons">
|
3
|
-
<button id="b1" data-page="
|
4
|
-
<button id="b2" data-page="
|
5
|
-
<button id="b3" data-page="
|
6
|
-
<button id="b4" data-page="
|
7
|
-
<button id="b5" data-page="
|
8
|
-
<button id="b6" data-page="
|
9
|
-
<button id="b7" data-page="
|
10
|
-
<button id="b8" data-page="
|
11
|
-
<button id="b9" data-page="
|
12
|
-
<button id="b10" data-page="collections">Collections</button>
|
3
|
+
<button id="b1" data-page="calculator">Calculator Demo</button>
|
4
|
+
<button id="b2" data-page="inputs">Inputs Demo</button>
|
5
|
+
<button id="b3" data-page="sidebars">Sidebar Demo</button>
|
6
|
+
<button id="b4" data-page="scrolls">Scrolls Demo</button>
|
7
|
+
<button id="b5" data-page="navbar">Navbar Demo</button>
|
8
|
+
<button id="b6" data-page="alerts">Alerts Demo</button>
|
9
|
+
<button id="b7" data-page="lockers">Lockers Demo</button>
|
10
|
+
<button id="b8" data-page="http">HTTP Demo</button>
|
11
|
+
<button id="b9" data-page="collections">Collections</button>
|
13
12
|
</view>
|
14
13
|
</page>
|
@@ -5,5 +5,11 @@ class CollectionsPage < UnderOs::Page
|
|
5
5
|
@collection.on :item do |item, index|
|
6
6
|
item.children[0].text = "##{index + 1}"
|
7
7
|
end
|
8
|
+
@collection.on :select do |item|
|
9
|
+
item.addClass 'selected'
|
10
|
+
end
|
11
|
+
@collection.on :unselect do |item|
|
12
|
+
item.removeClass 'selected'
|
13
|
+
end
|
8
14
|
end
|
9
15
|
end
|
data/app/pages/http_page.rb
CHANGED
@@ -13,7 +13,11 @@ class HttpPage < UnderOs::Page
|
|
13
13
|
@locker.show
|
14
14
|
|
15
15
|
UnderOs::HTTP.get search_url do |response|
|
16
|
-
|
16
|
+
if image_url = parse_first_image_url(response)
|
17
|
+
@result.load image_url do
|
18
|
+
@locker.hide
|
19
|
+
end
|
20
|
+
else
|
17
21
|
@locker.hide
|
18
22
|
end
|
19
23
|
end
|
@@ -22,12 +26,13 @@ class HttpPage < UnderOs::Page
|
|
22
26
|
def search_url
|
23
27
|
query = @search.value
|
24
28
|
query = 'puppy' if query.empty?
|
29
|
+
query = String.new(query).url_encode
|
25
30
|
|
26
|
-
"https://
|
31
|
+
"https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=#{query}"
|
27
32
|
end
|
28
33
|
|
29
|
-
def parse_first_image_url(
|
30
|
-
|
34
|
+
def parse_first_image_url(response)
|
35
|
+
response.json["responseData"]["results"][0]["url"] rescue nil # ftw!
|
31
36
|
end
|
32
37
|
|
33
38
|
end
|
data/app/styles/collections.css
CHANGED
data/lib/under-os.rb
CHANGED
@@ -8,16 +8,14 @@ Motion::Project::App.instance_eval do
|
|
8
8
|
Dir.glob(File.dirname(__FILE__) + '/**/*.rb').reverse.each do |file|
|
9
9
|
app.files.insert(0, file) if file != __FILE__
|
10
10
|
end
|
11
|
-
end
|
12
11
|
|
13
|
-
setup_before_under_os *args do |app|
|
14
12
|
app.resources_dirs << File.dirname(__FILE__) + "/assets"
|
15
13
|
app.resources_dirs << "app/styles/" if File.exists?("app/styles")
|
16
14
|
app.resources_dirs << "app/layouts/" if File.exists?("app/layouts")
|
17
15
|
|
18
16
|
app.fonts << "fontawesome-webfont.ttf"
|
19
|
-
|
20
|
-
instance_exec app, &block
|
21
17
|
end
|
18
|
+
|
19
|
+
setup_before_under_os *args, &block
|
22
20
|
end
|
23
21
|
end
|
data/lib/under_os/color.rb
CHANGED
@@ -94,26 +94,28 @@ class UnderOs::Color
|
|
94
94
|
|
95
95
|
def color_from_string(name)
|
96
96
|
name = name.downcase.strip
|
97
|
-
name =
|
98
|
-
name = 'darkGray' if name == 'darkgray'
|
99
|
-
name = 'lightGray' if name == 'lightgray'
|
97
|
+
name = ALIASES[name] || name
|
100
98
|
|
101
99
|
return UIColor.send("#{name}Color") if IOS_COLORS.include?(name)
|
102
100
|
|
103
101
|
name = HTML_COLORS[name] || name
|
104
102
|
name = "#" + name[1]*2 + name[2]*2 + name[3]*2 if name =~ /^#[abcdef0-9]{3}$/
|
105
103
|
|
106
|
-
r, g, b, a =
|
107
|
-
|
108
|
-
|
104
|
+
r, g, b, a = color_2_rgba(name)
|
105
|
+
|
106
|
+
color_from_array(r, g, b, a || 1.0)
|
107
|
+
end
|
108
|
+
|
109
|
+
def color_2_rgba(color)
|
110
|
+
if color =~ /^#[abcdef0-9]{6}$/
|
111
|
+
hex_2_rgb(color)
|
112
|
+
elsif m = color.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d*)\s*\)$/)
|
109
113
|
[m[1].to_i, m[2].to_i, m[3].to_i]
|
110
|
-
elsif m =
|
114
|
+
elsif m = color.match(/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d*)\s*,\s*([\d\.]+)\s*\)$/)
|
111
115
|
[m[1].to_i, m[2].to_i, m[3].to_i, m[4].to_f]
|
112
116
|
else
|
113
|
-
raise "Malformed color spec: #{
|
117
|
+
raise "Malformed color spec: #{color.inspect}"
|
114
118
|
end
|
115
|
-
|
116
|
-
color_from_array(r, g, b, a || 1.0)
|
117
119
|
end
|
118
120
|
|
119
121
|
def color_from_param(param) # 0.0..1.0
|
@@ -144,6 +146,12 @@ class UnderOs::Color
|
|
144
146
|
end
|
145
147
|
end
|
146
148
|
|
149
|
+
ALIASES = {
|
150
|
+
'transparent' => 'clear',
|
151
|
+
'darkgray' => 'darkGray',
|
152
|
+
'lightgray' => 'lightGray'
|
153
|
+
}
|
154
|
+
|
147
155
|
IOS_COLORS = %w[
|
148
156
|
black
|
149
157
|
darkGray
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class JSON
|
2
|
+
class Malformed < StandardError ; end
|
3
|
+
|
4
|
+
def self.parse(string, encoding=nil)
|
5
|
+
error = Pointer.new(:object)
|
6
|
+
data = NSJSONSerialization.JSONObjectWithData string.to_data(encoding), options:0, error:error
|
7
|
+
|
8
|
+
if error[0]
|
9
|
+
raise Malformed
|
10
|
+
else
|
11
|
+
data
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.generate(object, pretty=false)
|
16
|
+
options = pretty ? NSJSONWritingPrettyPrinted : 0
|
17
|
+
NSJSONSerialization.dataWithJSONObject(object, options:options, error:nil).to_s
|
18
|
+
end
|
19
|
+
end
|
data/lib/under_os/core/string.rb
CHANGED
@@ -37,4 +37,44 @@ class String
|
|
37
37
|
end
|
38
38
|
constant
|
39
39
|
end
|
40
|
+
|
41
|
+
def url_encode(encoding=nil)
|
42
|
+
stringByAddingPercentEscapesUsingEncoding ENCODINGS[encoding] || NSUTF8StringEncoding
|
43
|
+
end
|
44
|
+
|
45
|
+
def url_decode(encoding=nil)
|
46
|
+
stringByReplacingPercentEscapesUsingEncoding ENCODINGS[encoding] || NSUTF8StringEncoding
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_data(encoding=nil)
|
50
|
+
dataUsingEncoding ENCODINGS[encoding] || NSUTF8StringEncoding
|
51
|
+
end
|
52
|
+
|
53
|
+
ENCODINGS = {
|
54
|
+
'utf-8' => NSUTF8StringEncoding,
|
55
|
+
'utf-16' => NSUTF16StringEncoding,
|
56
|
+
'utf-32' => NSUTF32StringEncoding,
|
57
|
+
'ascii' => NSASCIIStringEncoding,
|
58
|
+
'latin1' => NSISOLatin1StringEncoding,
|
59
|
+
'latin2' => NSISOLatin2StringEncoding,
|
60
|
+
'cp1250' => NSWindowsCP1250StringEncoding,
|
61
|
+
'cp1251' => NSWindowsCP1251StringEncoding,
|
62
|
+
'cp1252' => NSWindowsCP1252StringEncoding,
|
63
|
+
'cp1253' => NSWindowsCP1253StringEncoding,
|
64
|
+
'cp1254' => NSWindowsCP1254StringEncoding,
|
65
|
+
|
66
|
+
|
67
|
+
# NSNEXTSTEPStringEncoding = 2,
|
68
|
+
# NSJapaneseEUCStringEncoding = 3,
|
69
|
+
# NSSymbolStringEncoding = 6,
|
70
|
+
# NSNonLossyASCIIStringEncoding = 7,
|
71
|
+
# NSShiftJISStringEncoding = 8,
|
72
|
+
# NSISO2022JPStringEncoding = 21,
|
73
|
+
# NSMacOSRomanStringEncoding = 30,
|
74
|
+
# NSUTF16BigEndianStringEncoding = 0x90000100,
|
75
|
+
# NSUTF16LittleEndianStringEncoding = 0x94000100,
|
76
|
+
# NSUTF32BigEndianStringEncoding = 0x98000100,
|
77
|
+
# NSUTF32LittleEndianStringEncoding = 0x9c000100,
|
78
|
+
# NSProprietaryStringEncoding = 65536
|
79
|
+
}
|
40
80
|
end
|
data/lib/under_os/file.rb
CHANGED
@@ -69,7 +69,7 @@ class UnderOs::File
|
|
69
69
|
NSFileManager.defaultManager.createFileAtPath @path, contents:nil, attributes:nil
|
70
70
|
end
|
71
71
|
|
72
|
-
content = content.
|
72
|
+
content = content.to_data('utf-8') if content.is_a?(String)
|
73
73
|
|
74
74
|
open
|
75
75
|
@handle.writeData content
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#
|
2
|
+
# A simple cookie jar thing
|
3
|
+
#
|
4
|
+
class UnderOs::HTTP::Cookies
|
5
|
+
def initialize(cookies, url)
|
6
|
+
@url = url.is_a?(String) ? NSURL.URLWithString(url) : url
|
7
|
+
@hash = cookies
|
8
|
+
end
|
9
|
+
|
10
|
+
def headers
|
11
|
+
NSHTTPCookie.requestHeaderFieldsWithCookies(ios_cookies)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
headers["Cookie"]
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def ios_cookies
|
21
|
+
@hash.map do |key, value|
|
22
|
+
NSHTTPCookie.cookieWithProperties({
|
23
|
+
NSHTTPCookieDomain => @url.host,
|
24
|
+
NSHTTPCookiePath => "/",
|
25
|
+
NSHTTPCookieName => key.to_s,
|
26
|
+
NSHTTPCookieValue => value.to_s
|
27
|
+
})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
#
|
2
2
|
# Options:
|
3
3
|
#
|
4
|
-
# * :method
|
5
|
-
# * :cookies
|
6
|
-
# * :stream
|
4
|
+
# * :method - GET, POST, ...
|
5
|
+
# * :cookies - Hash of cookie values
|
6
|
+
# * :stream - boolean, in case you want to stream stuff
|
7
|
+
# * :params - the POST/PUT/PATCH params hash
|
8
|
+
# * :encoding - the POST data encoding
|
7
9
|
#
|
8
10
|
# Events:
|
9
11
|
#
|
@@ -37,10 +39,14 @@ class UnderOs::HTTP::Request
|
|
37
39
|
@receiver = Receiver.new(self, @options[:stream])
|
38
40
|
@connection = NSURLConnection.alloc.initWithRequest(@request, delegate:@receiver)
|
39
41
|
@connection.start
|
42
|
+
|
43
|
+
return self
|
40
44
|
end
|
41
45
|
|
42
46
|
def cancel
|
43
47
|
@connection.cancel
|
48
|
+
|
49
|
+
return self
|
44
50
|
end
|
45
51
|
|
46
52
|
def method
|
@@ -58,32 +64,43 @@ class UnderOs::HTTP::Request
|
|
58
64
|
@options[:cookies] || {}
|
59
65
|
end
|
60
66
|
|
67
|
+
def params
|
68
|
+
@options[:params] || {}
|
69
|
+
end
|
70
|
+
|
71
|
+
def encoding
|
72
|
+
@options[:encoding] || 'utf-8'
|
73
|
+
end
|
74
|
+
|
61
75
|
protected
|
62
76
|
|
63
77
|
def build_request
|
64
|
-
|
65
|
-
|
66
|
-
request.setHTTPMethod self.method
|
67
|
-
#request.setHTTPBody self.params
|
68
|
-
|
69
|
-
cookies = self.cookies.map do |key, value|
|
70
|
-
NSHTTPCookie.cookieWithProperties({
|
71
|
-
NSHTTPCookieDomain => url.host,
|
72
|
-
NSHTTPCookiePath => "/",
|
73
|
-
NSHTTPCookieName => key.to_s,
|
74
|
-
NSHTTPCookieValue => value.to_s
|
75
|
-
})
|
76
|
-
end
|
78
|
+
query = params.to_query
|
79
|
+
url = build_url(query)
|
77
80
|
|
78
|
-
|
81
|
+
NSMutableURLRequest.requestWithURL(url).tap do |request|
|
82
|
+
request.setHTTPMethod method
|
79
83
|
|
80
|
-
headers.each do |key, value|
|
84
|
+
headers.merge(UnderOs::HTTP::Cookies.new(cookies, url).headers).each do |key, value|
|
81
85
|
request.addValue value, forHTTPHeaderField:key
|
82
86
|
end
|
83
87
|
|
84
|
-
|
85
|
-
|
88
|
+
if %w[POST PUT PATCH DELETE].include?(method) && !query.empty?
|
89
|
+
request.addValue "application/x-www-form-urlencoded;charset=#{encoding}", forHTTPHeaderField:"Content-Type"
|
90
|
+
request.setHTTPBody query.to_data(encoding)
|
91
|
+
end
|
86
92
|
end
|
87
93
|
end
|
94
|
+
|
95
|
+
def build_url(query)
|
96
|
+
url = @url
|
97
|
+
|
98
|
+
if method == "GET" && !query.empty?
|
99
|
+
url += url.include?('?') ? '&' : '?'
|
100
|
+
url += query
|
101
|
+
end
|
102
|
+
|
103
|
+
NSURL.URLWithString(url)
|
104
|
+
end
|
88
105
|
end
|
89
106
|
|
data/lib/under_os/http.rb
CHANGED
@@ -1,5 +1,31 @@
|
|
1
1
|
class UnderOs::HTTP
|
2
2
|
def self.get(url, options={}, &block)
|
3
|
-
|
3
|
+
request url, options.merge(method: :get), &block
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.post(url, options={}, &block)
|
7
|
+
request url, options.merge(method: :post), &block
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.put(url, options={}, &block)
|
11
|
+
request url, options.merge(method: :put), &block
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.patch(url, options={}, &block)
|
15
|
+
request url, options.merge(method: :patch), &block
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.head(url, options={}, &block)
|
19
|
+
request url, options.merge(method: :head), &block
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.delete(url, options={}, &block)
|
23
|
+
request url, options.merge(method: :delete), &block
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def self.request(*args, &block)
|
29
|
+
Request.new(*args, &block).send
|
4
30
|
end
|
5
31
|
end
|
@@ -59,10 +59,12 @@ class UnderOs::UI::Collection::Delegate < UIViewController
|
|
59
59
|
################################################################
|
60
60
|
|
61
61
|
def collectionView(collection, didSelectItemAtIndexPath: indexPath)
|
62
|
-
|
62
|
+
item = collection.cellForItemAtIndexPath(indexPath).uos_view_for(@collection)
|
63
|
+
@collection.emit(:select, item: item, index: indexPath.row, section: indexPath.section)
|
63
64
|
end
|
64
65
|
|
65
66
|
def collectionView(collection, didDeselectItemAtIndexPath: indexPath)
|
66
|
-
|
67
|
+
item = collection.cellForItemAtIndexPath(indexPath).uos_view_for(@collection)
|
68
|
+
@collection.emit(:unselect, item: item, index: indexPath.row, section: indexPath.section)
|
67
69
|
end
|
68
70
|
end
|
@@ -14,7 +14,7 @@ class UnderOs::UI::Collection < UnderOs::UI::View
|
|
14
14
|
|
15
15
|
def on(*args, &block)
|
16
16
|
super *args do |event|
|
17
|
-
params = [event.item, event.index, event.section]
|
17
|
+
params = [event.item, event.index, event.section]
|
18
18
|
params = params.slice(0, block.arity) if block.arity > -1
|
19
19
|
|
20
20
|
block.call *params
|
@@ -40,6 +40,7 @@ class UnderOs::UI::Collection < UnderOs::UI::View
|
|
40
40
|
|
41
41
|
def reload
|
42
42
|
@_.reloadData
|
43
|
+
self
|
43
44
|
end
|
44
45
|
|
45
46
|
def number_of_items(section=0)
|
@@ -48,6 +49,7 @@ class UnderOs::UI::Collection < UnderOs::UI::View
|
|
48
49
|
|
49
50
|
def number_of_items=(value)
|
50
51
|
@number_of_items = value.is_a?(Numeric) ? [value] : value
|
52
|
+
reload
|
51
53
|
end
|
52
54
|
|
53
55
|
def number_of_sections
|
data/lib/under_os/ui/locker.rb
CHANGED
@@ -22,39 +22,33 @@ module UnderOs::UI
|
|
22
22
|
|
23
23
|
def textAlign
|
24
24
|
if @view.is_a?(UIButton)
|
25
|
-
|
26
|
-
when UIControlContentHorizontalAlignmentRight then 'right'
|
27
|
-
when UIControlContentHorizontalAlignmentCenter then 'center'
|
28
|
-
when UIControlContentHorizontalAlignmentFill then 'justify'
|
29
|
-
else 'left'
|
30
|
-
end
|
25
|
+
BUTTONS_ALIGMENTS_MAP.key(@view.contentHorizontalAlignment)
|
31
26
|
elsif @view.respond_to?(:textAlignment)
|
32
|
-
|
33
|
-
when NSTextAlignmentRight then 'right'
|
34
|
-
when NSTextAlignmentCenter then 'center'
|
35
|
-
when NSTextAlignmentJustified then 'justify'
|
36
|
-
else 'left'
|
37
|
-
end
|
27
|
+
TEXTNODES_ALIGMENTS_MAP.key(@view.textAlignment)
|
38
28
|
end
|
39
29
|
end
|
40
30
|
|
41
31
|
def textAlign=(value)
|
42
32
|
if @view.is_a?(UIButton)
|
43
|
-
@view.contentHorizontalAlignment =
|
44
|
-
when 'right' then UIControlContentHorizontalAlignmentRight
|
45
|
-
when 'center' then UIControlContentHorizontalAlignmentCenter
|
46
|
-
when 'justify' then UIControlContentHorizontalAlignmentFill
|
47
|
-
else UIControlContentHorizontalAlignmentLeft
|
48
|
-
end
|
33
|
+
@view.contentHorizontalAlignment = BUTTONS_ALIGMENTS_MAP[value.to_s] || BUTTONS_ALIGMENTS_MAP['left']
|
49
34
|
elsif @view.respond_to?(:textAlignment)
|
50
|
-
@view.textAlignment =
|
51
|
-
when 'right' then NSTextAlignmentRight
|
52
|
-
when 'center' then NSTextAlignmentCenter
|
53
|
-
when 'justify' then NSTextAlignmentJustified
|
54
|
-
else NSTextAlignmentLeft
|
55
|
-
end
|
35
|
+
@view.textAlignment = TEXTNODES_ALIGMENTS_MAP[value.to_s] || BUTTONS_ALIGMENTS_MAP['left']
|
56
36
|
end
|
57
37
|
end
|
38
|
+
|
39
|
+
BUTTONS_ALIGMENTS_MAP = {
|
40
|
+
'right' => UIControlContentHorizontalAlignmentRight,
|
41
|
+
'center' => UIControlContentHorizontalAlignmentCenter,
|
42
|
+
'justify' => UIControlContentHorizontalAlignmentFill,
|
43
|
+
'left' => UIControlContentHorizontalAlignmentLeft
|
44
|
+
}
|
45
|
+
|
46
|
+
TEXTNODES_ALIGMENTS_MAP = {
|
47
|
+
'right' => NSTextAlignmentRight,
|
48
|
+
'center' => NSTextAlignmentCenter,
|
49
|
+
'justify' => NSTextAlignmentJustified,
|
50
|
+
'left' => NSTextAlignmentLeft
|
51
|
+
}
|
58
52
|
end
|
59
53
|
end
|
60
54
|
end
|
@@ -19,11 +19,8 @@ module UnderOs::UI
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def margin=(value)
|
22
|
-
|
23
|
-
|
24
|
-
self.marginLeft = value[3]
|
25
|
-
self.marginRight = value[1]
|
26
|
-
self.marginBottom = value[2]
|
22
|
+
@margin_top, @margin_right, @margin_botom, @margin_left = to_4dim_array(value)
|
23
|
+
set_offsets
|
27
24
|
end
|
28
25
|
|
29
26
|
def marginTop
|
@@ -67,11 +64,8 @@ module UnderOs::UI
|
|
67
64
|
end
|
68
65
|
|
69
66
|
def padding=(value)
|
70
|
-
|
71
|
-
|
72
|
-
self.paddingLeft = value[3]
|
73
|
-
self.paddingRight = value[1]
|
74
|
-
self.paddingBottom = value[2]
|
67
|
+
@padding_top, @padding_right, @padding_botom, @padding_left = to_4dim_array(value)
|
68
|
+
set_offsets
|
75
69
|
end
|
76
70
|
|
77
71
|
def paddingTop
|
@@ -113,10 +107,7 @@ module UnderOs::UI
|
|
113
107
|
private
|
114
108
|
|
115
109
|
def to_4dim_array(value)
|
116
|
-
if value.is_a?(String)
|
117
|
-
value = value.gsub('px', '').strip.split().reject(&:blank?).map(&:to_f)
|
118
|
-
end
|
119
|
-
|
110
|
+
value = value.gsub('px', '').split.map(&:to_f) if value.is_a?(String)
|
120
111
|
value = Array(value)
|
121
112
|
case value.size
|
122
113
|
when 1 then value * 4
|
@@ -128,32 +119,45 @@ module UnderOs::UI
|
|
128
119
|
def set_offsets
|
129
120
|
return nil if display != :inline
|
130
121
|
|
131
|
-
position_x
|
132
|
-
position_y
|
122
|
+
position_x = marginLeft + parent_offset_x
|
123
|
+
position_y = marginTop
|
133
124
|
|
134
|
-
|
135
|
-
|
125
|
+
@view.frame = [[position_x, position_y], [
|
126
|
+
@view.frame.size.width, @view.frame.size.height
|
127
|
+
]]
|
128
|
+
end
|
129
|
+
|
130
|
+
def set_paddings
|
131
|
+
if @view.respond_to?(:contentEdgeInsets)
|
132
|
+
@view.contentEdgeInsets = UIEdgeInsetsMake(paddingTop, paddingLeft, paddingBottom, paddingRight)
|
133
|
+
end
|
134
|
+
end
|
136
135
|
|
137
|
-
|
138
|
-
|
139
|
-
|
136
|
+
def parent_offset_x
|
137
|
+
offset = 0
|
138
|
+
parent_frame = parent_view_frame
|
140
139
|
|
141
|
-
|
140
|
+
if parent_frame
|
141
|
+
offset += parent_frame.origin.x + parent_frame.size.width
|
142
142
|
|
143
|
-
if wrap = UnderOs::UI::View.wrap_for(view)
|
144
|
-
|
143
|
+
if wrap = UnderOs::UI::View.wrap_for(@view)
|
144
|
+
offset += wrap.style.marginRight
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
148
|
-
|
149
|
-
view.frame.size.width, view.frame.size.height
|
150
|
-
]]
|
148
|
+
offset
|
151
149
|
end
|
152
150
|
|
153
|
-
def
|
154
|
-
|
155
|
-
|
151
|
+
def parent_view_frame
|
152
|
+
parent_view = @view.superview
|
153
|
+
parent_frame = nil
|
154
|
+
|
155
|
+
unless parent_view.subviews[0] === @view
|
156
|
+
previous_view = parent_view.subviews[parent_view.subviews.index(@view)-1]
|
157
|
+
parent_frame = previous_view && previous_view.frame
|
156
158
|
end
|
159
|
+
|
160
|
+
parent_frame
|
157
161
|
end
|
158
162
|
end
|
159
163
|
end
|
data/lib/under_os.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
describe Hash do
|
2
|
+
describe '#to_query' do
|
3
|
+
it "converts a simple hash into a query string" do
|
4
|
+
{a: 1, b: 2}.to_query.should == 'a=1&b=2'
|
5
|
+
end
|
6
|
+
|
7
|
+
it "converts nested hashes into queries correctly" do
|
8
|
+
{a: 1, b: {c: {d: 4}}}.to_query.should == 'a=1&b%5Bc%5D%5Bd%5D=4'
|
9
|
+
end
|
10
|
+
|
11
|
+
it "handles array values correctly" do
|
12
|
+
{a: [1,2,3,4]}.to_query.should == 'a%5B%5D=1&a%5B%5D=2&a%5B%5D=3&a%5B%5D=4'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "escapes any URL sensitive characters in the values" do
|
16
|
+
{a: '%= '}.to_query.should == 'a=%25=%20'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
describe JSON do
|
2
|
+
describe ".parse" do
|
3
|
+
it "parses correct json strings" do
|
4
|
+
JSON.parse('{"a":1,"b":true,"c":["data"]}').should == {
|
5
|
+
"a" => 1, "b" => true, "c" => ["data"]
|
6
|
+
}
|
7
|
+
end
|
8
|
+
|
9
|
+
it "raises an exception on malformed data" do
|
10
|
+
-> {
|
11
|
+
JSON.parse("malformed")
|
12
|
+
}.should.raise(JSON::Malformed)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ".generate" do
|
17
|
+
it "generates JSON string out of objects" do
|
18
|
+
JSON.generate({a:1, b:true, c:[:data]}).should ==
|
19
|
+
'{"a":1,"b":true,"c":["data"]}'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "generates pretty print when asked" do
|
23
|
+
JSON.generate({a:1, b:true, c:[:data]}, :pretty).should ==
|
24
|
+
"{\n \"a\" : 1,\n \"b\" : true,\n \"c\" : [\n \"data\"\n ]\n}"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "allows to export things directly of objects" do
|
28
|
+
{a:1, b:true, c:[:data]}.to_json.should ==
|
29
|
+
'{"a":1,"b":true,"c":["data"]}'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -84,4 +84,38 @@ describe String do
|
|
84
84
|
}.should.raise(NameError)
|
85
85
|
end
|
86
86
|
end
|
87
|
+
|
88
|
+
describe '#url_encode' do
|
89
|
+
it "escapes all the URL sensitive symbols" do
|
90
|
+
"!*'\"();:@&=+$,/?%#[]% ".url_encode.should == "!*'%22();:@&=+$,/?%25%23%5B%5D%25%20"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "doesn't touch normal characters" do
|
94
|
+
"Hello World".url_encode.should == "Hello%20World"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#url_decode' do
|
99
|
+
it "converts an url encoded string back to normality" do
|
100
|
+
"!*'%22();:@&=+$,/?%25%23%5B%5D%25%20".url_decode.should == "!*'\"();:@&=+$,/?%#[]% "
|
101
|
+
end
|
102
|
+
|
103
|
+
it "doesn't break normal characters" do
|
104
|
+
"Hello%20World".url_decode.should == "Hello World"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#to_data' do
|
109
|
+
before do
|
110
|
+
@data = "ohai there".to_data
|
111
|
+
end
|
112
|
+
|
113
|
+
it "converts the string into a data object" do
|
114
|
+
@data.is_a?(NSData).should == true
|
115
|
+
end
|
116
|
+
|
117
|
+
it "converts it into data with correct content" do
|
118
|
+
@data.to_s.should == "ohai there"
|
119
|
+
end
|
120
|
+
end
|
87
121
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
describe UnderOS::HTTP::Cookies do
|
2
|
+
before do
|
3
|
+
@cookies = UnderOS::HTTP::Cookies.new({a: 1, b: true}, "http://test.com")
|
4
|
+
end
|
5
|
+
|
6
|
+
it "allows to export them in a string" do
|
7
|
+
@cookies.to_s.should == "a=1; b=true"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "allows to export them into an HTTP header hash" do
|
11
|
+
@cookies.headers.should == {"Cookie"=>"a=1; b=true"}
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
describe UnderOS::HTTP::Request do
|
2
|
+
before do
|
3
|
+
@url = "http://test.com"
|
4
|
+
@request = UnderOS::HTTP::Request.new(@url, {
|
5
|
+
headers: {my: 'headers'},
|
6
|
+
cookies: {my: 'cookies'},
|
7
|
+
params: {my: 'params'},
|
8
|
+
method: :put
|
9
|
+
})
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#constructor" do
|
13
|
+
it "assigns the url correctly" do
|
14
|
+
@request.url.should == @url
|
15
|
+
end
|
16
|
+
|
17
|
+
it "assigns the request headers correctly" do
|
18
|
+
@request.headers.should == {my: 'headers'}
|
19
|
+
end
|
20
|
+
|
21
|
+
it "assigns the request cookies correctly" do
|
22
|
+
@request.cookies.should == {my: 'cookies'}
|
23
|
+
end
|
24
|
+
|
25
|
+
it "assigns my params correctly" do
|
26
|
+
@request.params.should == {my: 'params'}
|
27
|
+
end
|
28
|
+
|
29
|
+
it "assigns the request method correctly" do
|
30
|
+
@request.method.should == 'PUT'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#on" do
|
35
|
+
it "returns the response object instead of an event into a callback" do
|
36
|
+
@response = nil
|
37
|
+
|
38
|
+
@request.on(:smth) { |r| @response = r }
|
39
|
+
@request.emit(:smth, response: 'response')
|
40
|
+
|
41
|
+
@response.should == 'response'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
describe UnderOs::HTTP do
|
2
|
+
extend Facon::SpecHelpers
|
3
|
+
|
4
|
+
before do
|
5
|
+
@url = 'http://test.com'
|
6
|
+
@req = mock 'request', send: :request
|
7
|
+
end
|
8
|
+
|
9
|
+
%w[get post put patch head delete].each do |method|
|
10
|
+
describe ".#{method}" do
|
11
|
+
it "sends a #{method.upcase} request" do
|
12
|
+
UnderOs::HTTP::Request.should.receive(:new)
|
13
|
+
.with(@url, foo: 'bar', method: method.to_sym)
|
14
|
+
.and_return(@req)
|
15
|
+
|
16
|
+
UnderOs::HTTP.__send__(method, @url, foo: 'bar').should == :request
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/under-os.gemspec
CHANGED
@@ -16,8 +16,6 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
|
19
|
-
gem.add_development_dependency 'rake'
|
20
|
-
|
21
19
|
gem.post_install_message = %Q{
|
22
20
|
If you want to use the UnderOS template with RubyMotion, please run the following:
|
23
21
|
|
@@ -29,4 +27,8 @@ Gem::Specification.new do |gem|
|
|
29
27
|
|
30
28
|
motion create awesomness --template=uos
|
31
29
|
}
|
30
|
+
|
31
|
+
gem.add_development_dependency 'rake'
|
32
|
+
gem.add_development_dependency 'motion-facon'
|
33
|
+
|
32
34
|
end
|
metadata
CHANGED
@@ -1,27 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: under-os
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nikolay Nemshilov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-12-
|
11
|
+
date: 2013-12-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: motion-facon
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0'
|
27
41
|
description: A web-broser like wrapper over iOS
|
@@ -31,7 +45,8 @@ executables: []
|
|
31
45
|
extensions: []
|
32
46
|
extra_rdoc_files: []
|
33
47
|
files:
|
34
|
-
-
|
48
|
+
- .gitignore
|
49
|
+
- .travis.yml
|
35
50
|
- Gemfile
|
36
51
|
- Gemfile.lock
|
37
52
|
- README.md
|
@@ -57,7 +72,6 @@ files:
|
|
57
72
|
- app/pages/navbar_page.rb
|
58
73
|
- app/pages/scrolls_page.rb
|
59
74
|
- app/pages/sidebars_page.rb
|
60
|
-
- app/pages/stuff_page.rb
|
61
75
|
- app/styles/application.css
|
62
76
|
- app/styles/calculator.css
|
63
77
|
- app/styles/collections.css
|
@@ -73,14 +87,19 @@ files:
|
|
73
87
|
- lib/under_os/app.rb
|
74
88
|
- lib/under_os/color.rb
|
75
89
|
- lib/under_os/config.rb
|
90
|
+
- lib/under_os/core/array.rb
|
91
|
+
- lib/under_os/core/hash.rb
|
92
|
+
- lib/under_os/core/json.rb
|
76
93
|
- lib/under_os/core/kernel.rb
|
77
94
|
- lib/under_os/core/numeric.rb
|
95
|
+
- lib/under_os/core/object.rb
|
78
96
|
- lib/under_os/core/string.rb
|
79
97
|
- lib/under_os/delegate.rb
|
80
98
|
- lib/under_os/events.rb
|
81
99
|
- lib/under_os/file.rb
|
82
100
|
- lib/under_os/history.rb
|
83
101
|
- lib/under_os/http.rb
|
102
|
+
- lib/under_os/http/cookies.rb
|
84
103
|
- lib/under_os/http/receiver.rb
|
85
104
|
- lib/under_os/http/request.rb
|
86
105
|
- lib/under_os/http/response.rb
|
@@ -144,11 +163,16 @@ files:
|
|
144
163
|
- spec/assets/test.css
|
145
164
|
- spec/assets/test.html
|
146
165
|
- spec/assets/test_page.rb
|
166
|
+
- spec/lib/core/hash_spec.rb
|
167
|
+
- spec/lib/core/json_spec.rb
|
147
168
|
- spec/lib/core/numeric_spec.rb
|
148
169
|
- spec/lib/core/string_spec.rb
|
149
170
|
- spec/lib/under_os/color_spec.rb
|
150
171
|
- spec/lib/under_os/events_spec.rb
|
151
172
|
- spec/lib/under_os/file_spec.rb
|
173
|
+
- spec/lib/under_os/http/cookies_spec.rb
|
174
|
+
- spec/lib/under_os/http/request_spec.rb
|
175
|
+
- spec/lib/under_os/http_spec.rb
|
152
176
|
- spec/lib/under_os/page/builder_spec.rb
|
153
177
|
- spec/lib/under_os/page/layout_spec.rb
|
154
178
|
- spec/lib/under_os/page/matcher_spec.rb
|
@@ -201,17 +225,17 @@ require_paths:
|
|
201
225
|
- lib
|
202
226
|
required_ruby_version: !ruby/object:Gem::Requirement
|
203
227
|
requirements:
|
204
|
-
- -
|
228
|
+
- - '>='
|
205
229
|
- !ruby/object:Gem::Version
|
206
230
|
version: '0'
|
207
231
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
208
232
|
requirements:
|
209
|
-
- -
|
233
|
+
- - '>='
|
210
234
|
- !ruby/object:Gem::Version
|
211
235
|
version: '0'
|
212
236
|
requirements: []
|
213
237
|
rubyforge_project:
|
214
|
-
rubygems_version: 2.
|
238
|
+
rubygems_version: 2.1.11
|
215
239
|
signing_key:
|
216
240
|
specification_version: 4
|
217
241
|
summary: A web-broser like wrapper over iOS using RubyMotion
|
@@ -220,11 +244,16 @@ test_files:
|
|
220
244
|
- spec/assets/test.css
|
221
245
|
- spec/assets/test.html
|
222
246
|
- spec/assets/test_page.rb
|
247
|
+
- spec/lib/core/hash_spec.rb
|
248
|
+
- spec/lib/core/json_spec.rb
|
223
249
|
- spec/lib/core/numeric_spec.rb
|
224
250
|
- spec/lib/core/string_spec.rb
|
225
251
|
- spec/lib/under_os/color_spec.rb
|
226
252
|
- spec/lib/under_os/events_spec.rb
|
227
253
|
- spec/lib/under_os/file_spec.rb
|
254
|
+
- spec/lib/under_os/http/cookies_spec.rb
|
255
|
+
- spec/lib/under_os/http/request_spec.rb
|
256
|
+
- spec/lib/under_os/http_spec.rb
|
228
257
|
- spec/lib/under_os/page/builder_spec.rb
|
229
258
|
- spec/lib/under_os/page/layout_spec.rb
|
230
259
|
- spec/lib/under_os/page/matcher_spec.rb
|
data/app/pages/stuff_page.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
class StuffPage < UnderOs::Page
|
2
|
-
def initialize
|
3
|
-
self.title = "Various Stuff"
|
4
|
-
|
5
|
-
@box = View.new(style: {
|
6
|
-
top: 50,
|
7
|
-
left: 50,
|
8
|
-
width: 100,
|
9
|
-
height: 100,
|
10
|
-
background: :red,
|
11
|
-
borderRadius: 10,
|
12
|
-
borderWidth: 2,
|
13
|
-
borderColor: :green
|
14
|
-
})
|
15
|
-
|
16
|
-
@box.on(:tap){ @box.fade_out.fade_in }
|
17
|
-
|
18
|
-
@b2 = View.new(style: {background: :blue})
|
19
|
-
@b2.size = {x: 50, y: 50}
|
20
|
-
@b2.position = {x: 25, y: 25}
|
21
|
-
|
22
|
-
@b2.on(:tap, :highlight)
|
23
|
-
|
24
|
-
insert @box.insert(@b2)
|
25
|
-
|
26
|
-
insert Button.new(text: 'Boo Hoo!').position(x: 100, y: 200)
|
27
|
-
|
28
|
-
insert Label.new(text: "Hey Label", style: {background: :red}).position({x: 100, y: 250})
|
29
|
-
|
30
|
-
insert Icon.new(:cog).position(x: 50, y: 300)
|
31
|
-
insert Icon.new(:trash).position(x: 100, y: 300)
|
32
|
-
insert Icon.new(:home).position(x: 150, y: 300)
|
33
|
-
insert Icon.new(:magic).position(x: 200, y: 300)
|
34
|
-
end
|
35
|
-
end
|