motion-prime 0.5.5 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +1 -1
- data/motion-prime/app_delegate.rb +11 -8
- data/motion-prime/models/_association_mixin.rb +3 -0
- data/motion-prime/models/_base_mixin.rb +63 -16
- data/motion-prime/models/_finder_mixin.rb +10 -6
- data/motion-prime/models/_nano_bag_mixin.rb +4 -4
- data/motion-prime/models/_sync_mixin.rb +65 -12
- data/motion-prime/screens/_base_mixin.rb +5 -0
- data/motion-prime/screens/_navigation_mixin.rb +14 -12
- data/motion-prime/sections/base_section.rb +42 -0
- data/motion-prime/sections/table.rb +3 -0
- data/motion-prime/sections/table/table_delegate.rb +4 -0
- data/motion-prime/support/tab_bar_controller.rb +5 -6
- data/motion-prime/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NWRjNTUxZWEzMTQzYjA3YTQ1ZjY4YmU2ZDdlZGQ3OGY1MzQ0NzJhYw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDAyNzdlMjM1N2U0Mzk2MmFhNzJmZTM1OGRhNGVmMjBjMjEzZTkwYQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MDFlYjZhYjMxOTM0NjIxMTYzZDQ3ZjA5M2ZkMTQzMTYyMmFmY2QzOWFlODU4
|
10
|
+
MTc1YTRmYjBhNjA0NDA0N2I5MjA0Y2U0ZWYxMzZmMjIyZWJkYWIzYjkxYWVj
|
11
|
+
ZmZjOTdkMGMxNTFiZWE5NGI4YTA2MDg3NjM5YTY4YmNiMTJjNzM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
N2FlNDdlYjQzZDUyZjVlZTZiNjA1MDA1ZGI4MjI5M2Q1ZjFkMzY5ZmI5OTVi
|
14
|
+
YjA3ZmU0NzNlN2E0YjI0ZTYyMjQ2NGJlOTliMDE0OTM2Mjg2NmExODljZDBk
|
15
|
+
ZmRiYTRiMGE4N2RkZTc3MmI1MjlhNGY1NjVjMDU1OTJlYWNmOWY=
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
=== 0.5.6
|
2
|
+
* sending "title" in options is not supported now. use dsl with Proc for that.
|
3
|
+
* ability to open root screen with animation.
|
4
|
+
* refactored screens navigation.
|
5
|
+
|
1
6
|
=== 0.5.5
|
2
7
|
* improve association fetch speed and login.
|
3
8
|
* "delete" method is not supported for model collection now, use delete_all.
|
data/Gemfile.lock
CHANGED
@@ -42,9 +42,9 @@ module MotionPrime
|
|
42
42
|
def open_screen(screen, options = {})
|
43
43
|
screen = prepare_screen_for_open(screen, options)
|
44
44
|
if options[:root] || !self.window
|
45
|
-
open_root_screen(screen)
|
45
|
+
open_root_screen(screen, options)
|
46
46
|
else
|
47
|
-
open_content_screen(screen)
|
47
|
+
open_content_screen(screen, options)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -62,7 +62,6 @@ module MotionPrime
|
|
62
62
|
|
63
63
|
private
|
64
64
|
def prepare_screen_for_open(screen, options = {})
|
65
|
-
screen = create_tab_bar(screen) if screen.is_a?(Array)
|
66
65
|
Screen.create_with_options(screen, true, options)
|
67
66
|
end
|
68
67
|
|
@@ -73,7 +72,15 @@ module MotionPrime
|
|
73
72
|
screen = screen.main_controller if screen.respond_to?(:main_controller)
|
74
73
|
|
75
74
|
self.window ||= UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
|
76
|
-
|
75
|
+
if options[:animated]
|
76
|
+
UIView.transitionWithView self.window,
|
77
|
+
duration: 0.5,
|
78
|
+
options: UIViewAnimationOptionTransitionFlipFromLeft,
|
79
|
+
animations: proc { self.window.rootViewController = screen },
|
80
|
+
completion: nil
|
81
|
+
else
|
82
|
+
self.window.rootViewController = screen
|
83
|
+
end
|
77
84
|
self.window.makeKeyAndVisible
|
78
85
|
screen
|
79
86
|
end
|
@@ -81,9 +88,5 @@ module MotionPrime
|
|
81
88
|
def open_content_screen(screen, options = {})
|
82
89
|
open_root_screen(screen)
|
83
90
|
end
|
84
|
-
|
85
|
-
def create_tab_bar(screens)
|
86
|
-
MotionPrime::TabBarController.new(screens)
|
87
|
-
end
|
88
91
|
end
|
89
92
|
end
|
@@ -6,6 +6,9 @@ module MotionPrime
|
|
6
6
|
base.class_attribute :default_sort_options
|
7
7
|
end
|
8
8
|
|
9
|
+
# Saves model to default store.
|
10
|
+
#
|
11
|
+
# @return [Prime::Model] model
|
9
12
|
def save
|
10
13
|
raise StoreError, 'No store provided' unless self.store
|
11
14
|
error_ptr = Pointer.new(:id)
|
@@ -14,6 +17,9 @@ module MotionPrime
|
|
14
17
|
self
|
15
18
|
end
|
16
19
|
|
20
|
+
# Removed model from default store.
|
21
|
+
#
|
22
|
+
# @return [Prime::Model] model
|
17
23
|
def delete
|
18
24
|
raise StoreError, 'No store provided' unless self.store
|
19
25
|
|
@@ -27,6 +33,13 @@ module MotionPrime
|
|
27
33
|
super || self.class.store
|
28
34
|
end
|
29
35
|
|
36
|
+
# Assigns attributes to model
|
37
|
+
#
|
38
|
+
# @params attributes [Hash] attributes to be assigned
|
39
|
+
# @params options [Hash] options
|
40
|
+
# @option options [Boolean] :skip_nil_values Do not assign nil values
|
41
|
+
# @option options [Boolean] :validate_attribute_presence Raise error if model do not have attribute
|
42
|
+
# @return [Hash] attributes
|
30
43
|
def assign_attributes(new_attributes, options = {})
|
31
44
|
attributes = new_attributes.symbolize_keys
|
32
45
|
attributes.each do |k, v|
|
@@ -40,30 +53,54 @@ module MotionPrime
|
|
40
53
|
end
|
41
54
|
end
|
42
55
|
|
56
|
+
# Assigns attribute to model
|
57
|
+
#
|
58
|
+
# @params name [String, Symbol] attribute name
|
59
|
+
# @params value [Object] attribute value
|
60
|
+
# @return [Object] assigned object if has been assigned
|
43
61
|
def assign_attribute(name, value)
|
44
62
|
self.send("#{name}=", value) if has_attribute?(name)
|
45
63
|
end
|
46
64
|
|
65
|
+
# Check if model has attribute
|
66
|
+
#
|
67
|
+
# @params name [String, Symbol] attribute name
|
68
|
+
# @return [Boolean] result
|
47
69
|
def has_attribute?(name)
|
48
70
|
respond_to?("#{name}=")
|
49
71
|
end
|
50
72
|
|
73
|
+
# Hash of all attributes in model
|
74
|
+
#
|
75
|
+
# @return [Hash] key-value hash
|
51
76
|
def attributes_hash
|
52
77
|
self.info.to_hash.symbolize_keys
|
53
78
|
end
|
54
79
|
|
80
|
+
# Checks if model has been saved in server (have an ID)
|
81
|
+
#
|
82
|
+
# @return [Boolean] true if model is not saved
|
55
83
|
def new_record?
|
56
84
|
id.blank?
|
57
85
|
end
|
58
86
|
|
87
|
+
# Checks if model has been saved in server (have an ID)
|
88
|
+
#
|
89
|
+
# @return [Boolean] true if model is saved
|
59
90
|
def persisted?
|
60
91
|
!new_record?
|
61
92
|
end
|
62
93
|
|
94
|
+
# Model class name
|
95
|
+
#
|
96
|
+
# @return [String] model class name
|
63
97
|
def model_name
|
64
98
|
self.class_name_without_kvo.underscore
|
65
99
|
end
|
66
100
|
|
101
|
+
# Returns json-formatted representation of model
|
102
|
+
#
|
103
|
+
# @return [String] model representation
|
67
104
|
def inspect
|
68
105
|
"#<#{self.class}:0x#{self.object_id.to_s(16)}> " + MotionPrime::JSON.generate(info)
|
69
106
|
end
|
@@ -71,9 +108,12 @@ module MotionPrime
|
|
71
108
|
module ClassMethods
|
72
109
|
# Initialize a new object
|
73
110
|
#
|
74
|
-
#
|
111
|
+
# @example:
|
75
112
|
# User.new(name: "Bob", age: 10)
|
76
113
|
#
|
114
|
+
# @params attributes [Hash] attributes beeing assigned to model
|
115
|
+
# @params options [Hash] options
|
116
|
+
# @option options [Boolean] :validate_attribute_presence Raise error if model do not have attribute
|
77
117
|
# @return MotionPrime::Model unsaved model
|
78
118
|
def new(data = {}, options = {})
|
79
119
|
data.keys.each do |key|
|
@@ -90,20 +130,22 @@ module MotionPrime
|
|
90
130
|
object
|
91
131
|
end
|
92
132
|
|
93
|
-
# Initialize a new object and save it
|
133
|
+
# Initialize a new object and save it to store
|
94
134
|
#
|
95
|
-
#
|
135
|
+
# @example:
|
96
136
|
# User.create(name: "Bob", age: 10)
|
97
137
|
#
|
98
|
-
# @
|
138
|
+
# @params attributes [Hash] attributes beeing assigned to model
|
139
|
+
# @return model [MotionPrime::Model] saved model
|
99
140
|
def create(data = {})
|
100
141
|
object = self.new(data)
|
101
142
|
object.save
|
143
|
+
object
|
102
144
|
end
|
103
145
|
|
104
146
|
# Define model attribute
|
105
147
|
#
|
106
|
-
#
|
148
|
+
# @example:
|
107
149
|
# class User < MotionPrime::Model
|
108
150
|
# attribute :name
|
109
151
|
# attribute :age
|
@@ -134,46 +176,45 @@ module MotionPrime
|
|
134
176
|
end
|
135
177
|
end
|
136
178
|
|
137
|
-
# Set or return all model attribute names
|
179
|
+
# Set and/or return all model attribute names
|
138
180
|
#
|
139
|
-
# @return Array array of attribute names
|
181
|
+
# @return array [Array<Symbol>] array of attribute names
|
140
182
|
def attributes(*attrs)
|
141
183
|
if attrs.size > 0
|
142
184
|
attrs.each{|attr| attribute attr}
|
143
|
-
else
|
144
|
-
@attributes ||= []
|
145
185
|
end
|
186
|
+
@attributes ||= []
|
146
187
|
end
|
147
188
|
|
148
189
|
# Return store associated with model class, or shared store by default
|
149
190
|
#
|
150
|
-
# @return MotionPrime::Store store
|
191
|
+
# @return store [MotionPrime::Store] store
|
151
192
|
def store
|
152
193
|
@store ||= MotionPrime::Store.shared_store
|
153
194
|
end
|
154
195
|
|
155
196
|
# Define store associated with model class
|
156
197
|
#
|
157
|
-
# @param MotionPrime::Store store
|
158
|
-
# @return MotionPrime::Store store
|
198
|
+
# @param store [MotionPrime::Store] store
|
199
|
+
# @return store [MotionPrime::Store] store
|
159
200
|
def store=(store)
|
160
201
|
@store = store
|
161
202
|
end
|
162
203
|
|
163
204
|
# Count of models
|
164
205
|
#
|
165
|
-
# @return Fixnum count
|
206
|
+
# @return count [Fixnum] count of objects with this Prime::Model
|
166
207
|
def count
|
167
208
|
self.store.count(self)
|
168
209
|
end
|
169
210
|
|
170
211
|
# Delete objects from store by given options
|
171
212
|
#
|
172
|
-
#
|
213
|
+
# @example:
|
173
214
|
# User.delete(:name => "Bob") #
|
174
215
|
#
|
175
|
-
# @param [Array, MotionPrime::Model] objects to delete
|
176
|
-
# @return [Array] removed item keys
|
216
|
+
# @param options [Hash, Array, MotionPrime::Model] objects to delete. See find_keys for list of options.
|
217
|
+
# @return keys [Array] removed item keys
|
177
218
|
def delete(*args)
|
178
219
|
if args.blank?
|
179
220
|
raise "Using delete with no args is not allowed. Please use delete_all to delete all records"
|
@@ -182,6 +223,12 @@ module MotionPrime
|
|
182
223
|
self.store.delete_keys(keys)
|
183
224
|
end
|
184
225
|
|
226
|
+
# Delete all objects with this Prime::Model
|
227
|
+
#
|
228
|
+
# @example:
|
229
|
+
# User.delete_all
|
230
|
+
#
|
231
|
+
# @return keys [Array] removed item keys
|
185
232
|
def delete_all
|
186
233
|
self.store.delete_keys(find_keys)
|
187
234
|
end
|
@@ -7,7 +7,7 @@ module MotionPrime
|
|
7
7
|
|
8
8
|
# Find all models
|
9
9
|
#
|
10
|
-
# @return [Array] array of models
|
10
|
+
# @return items [Array] array of models
|
11
11
|
def all(*args)
|
12
12
|
return [] unless self.store
|
13
13
|
|
@@ -26,23 +26,27 @@ module MotionPrime
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# Find last model model by default order
|
29
|
+
#
|
30
|
+
# @return item [Prime::Model] result
|
29
31
|
def last
|
30
32
|
all.last
|
31
33
|
end
|
32
34
|
|
33
35
|
# Find first model model by default order
|
36
|
+
#
|
37
|
+
# @return item [Prime::Model] result
|
34
38
|
def first
|
35
39
|
all.first
|
36
40
|
end
|
37
41
|
|
38
42
|
# Find model by criteria
|
39
43
|
#
|
40
|
-
#
|
44
|
+
# @example:
|
41
45
|
# User.find(:name, NSFEqualTo, "Bob") # => [<User#1>]
|
42
46
|
# User.find(:name => "Bob") # => [<User#1>]
|
43
47
|
# User.find(:name => {NSFEqualTo => "Bob"}) # => [<User#1>]
|
44
48
|
#
|
45
|
-
# @return [Array] array of models
|
49
|
+
# @return items [Array] array of models
|
46
50
|
def find(*arg)
|
47
51
|
if arg[0].is_a?(Hash)
|
48
52
|
# hash style
|
@@ -88,12 +92,12 @@ module MotionPrime
|
|
88
92
|
|
89
93
|
# Find model keys by criteria
|
90
94
|
#
|
91
|
-
#
|
95
|
+
# @example:
|
92
96
|
# User.find_keys(:name, NSFEqualTo, "Bob") # => ["1"]
|
93
97
|
# User.find_keys(:name => "Bob") # => ["1"]
|
94
98
|
# User.find_keys(:name => {NSFEqualTo => "Bob"}) # => ["1"]
|
95
99
|
#
|
96
|
-
# @return [Array] array of models
|
100
|
+
# @return keys [Array] array of models
|
97
101
|
def find_keys(*arg)
|
98
102
|
if arg[0].is_a?(Hash)
|
99
103
|
# hash style
|
@@ -140,7 +144,7 @@ module MotionPrime
|
|
140
144
|
|
141
145
|
# Find a model by key
|
142
146
|
#
|
143
|
-
#
|
147
|
+
# @example:
|
144
148
|
# User.find_by_key(my_key)
|
145
149
|
#
|
146
150
|
# @return [Object, Nil] an object or nil (if not found)
|
@@ -29,7 +29,7 @@ module MotionPrime
|
|
29
29
|
|
30
30
|
# Add an object or array of objects to bag
|
31
31
|
#
|
32
|
-
# @return self
|
32
|
+
# @return self [Prime::Model]
|
33
33
|
def add(object_or_array)
|
34
34
|
error_ptr = Pointer.new(:id)
|
35
35
|
prepared = prepare_for_store(object_or_array)
|
@@ -59,8 +59,8 @@ module MotionPrime
|
|
59
59
|
|
60
60
|
# Remove object from bag with key
|
61
61
|
#
|
62
|
-
# @param [String]
|
63
|
-
# @return self
|
62
|
+
# @param key [String] a key or array of keys
|
63
|
+
# @return self [Prime::Model]
|
64
64
|
def delete_key(key)
|
65
65
|
if key.is_a?(Array)
|
66
66
|
self.removeObjectsWithKeysInArray(key)
|
@@ -72,7 +72,7 @@ module MotionPrime
|
|
72
72
|
|
73
73
|
# Remove an object or array of objects from bag
|
74
74
|
#
|
75
|
-
# @param [
|
75
|
+
# @param items [Array<Prime::Model>, Prime::Model] model or array of models to remove
|
76
76
|
# @return self
|
77
77
|
def delete(object_or_array)
|
78
78
|
error_ptr = Pointer.new(:id)
|
@@ -8,19 +8,30 @@ module MotionPrime
|
|
8
8
|
base.class_attribute :_associations
|
9
9
|
end
|
10
10
|
|
11
|
+
# Get normalized sync url of this Prime::Model
|
12
|
+
#
|
13
|
+
# @param method [Symbol] http method
|
14
|
+
# @return url [String] url to use in model sync
|
11
15
|
def sync_url(method = :get, options = {})
|
12
16
|
url = self.class.sync_url
|
13
17
|
url = url.call(method, self, options) if url.is_a?(Proc)
|
14
18
|
normalize_sync_url(url)
|
15
19
|
end
|
16
20
|
|
21
|
+
# Get normalized sync url of associated Prime::Model
|
22
|
+
#
|
23
|
+
# @param key [Symbol] association name
|
24
|
+
# @return url [String] url to use in model association sync
|
17
25
|
def association_sync_url(key, options)
|
18
26
|
url = options[:sync_url]
|
19
27
|
url = url.call(self) if url.is_a?(Proc)
|
20
28
|
normalize_sync_url(url)
|
21
29
|
end
|
22
30
|
|
23
|
-
#
|
31
|
+
# Destroy model on server and delete on local
|
32
|
+
#
|
33
|
+
# @param block [Proc] block to be executed after destroy
|
34
|
+
# @return self[Prime::Model] deleted model.
|
24
35
|
def destroy(&block)
|
25
36
|
use_callback = block_given?
|
26
37
|
api_client.delete(sync_url(:delete)) do
|
@@ -29,12 +40,19 @@ module MotionPrime
|
|
29
40
|
delete
|
30
41
|
end
|
31
42
|
|
32
|
-
#
|
43
|
+
# Fetch model from server and save on local
|
44
|
+
#
|
33
45
|
def fetch!(options = {}, &block)
|
34
46
|
fetch(options.merge(save: true), &block)
|
35
47
|
end
|
36
48
|
|
37
|
-
#
|
49
|
+
# Fetch model from server
|
50
|
+
#
|
51
|
+
# @param options [Hash] fetch options
|
52
|
+
# @option options [Symbol] :method Http method to calculate url, `:get` by default
|
53
|
+
# @option options [Boolean] :associations Also fetch associations
|
54
|
+
# @option options [Boolean] :save Save model after fetch
|
55
|
+
# @param block [Proc] block to be executed after fetch
|
38
56
|
def fetch(options = {}, &block)
|
39
57
|
use_callback = block_given?
|
40
58
|
method = options[:method] || :get
|
@@ -54,12 +72,16 @@ module MotionPrime
|
|
54
72
|
end if will_fetch_associations
|
55
73
|
end
|
56
74
|
|
57
|
-
#
|
75
|
+
# Update on server and save response on local
|
76
|
+
#
|
58
77
|
def update!(options = {}, &block)
|
59
78
|
update(options.merge(save_response: true), &block)
|
60
79
|
end
|
61
80
|
|
62
|
-
#
|
81
|
+
# Update on server
|
82
|
+
# @param options [Hash] update options
|
83
|
+
# @option options [Symbol] :method Http method to calculate url, by default `:post` for new record and `:put` for existing
|
84
|
+
# @param block [Proc] block to be executed after update
|
63
85
|
def update(options = {}, &block)
|
64
86
|
use_callback = block_given?
|
65
87
|
|
@@ -72,7 +94,10 @@ module MotionPrime
|
|
72
94
|
end if will_update_model
|
73
95
|
end
|
74
96
|
|
75
|
-
#
|
97
|
+
# Fetch model from server using url
|
98
|
+
#
|
99
|
+
# @param url [String] url to fetch
|
100
|
+
# @param block [Proc] block to be executed after fetch
|
76
101
|
def fetch_with_url(url, &block)
|
77
102
|
use_callback = block_given?
|
78
103
|
api_client.get(url) do |data, status_code|
|
@@ -81,7 +106,10 @@ module MotionPrime
|
|
81
106
|
end
|
82
107
|
end
|
83
108
|
|
84
|
-
#
|
109
|
+
# Update on server using url
|
110
|
+
#
|
111
|
+
# @param url [String] url to update
|
112
|
+
# @param block [Proc] block to be executed after update
|
85
113
|
def update_with_url(url, options = {}, &block)
|
86
114
|
use_callback = block_given?
|
87
115
|
filtered_attributes = filtered_updatable_attributes(options)
|
@@ -109,14 +137,31 @@ module MotionPrime
|
|
109
137
|
fetch_with_attributes(data)
|
110
138
|
end
|
111
139
|
|
112
|
-
#
|
113
|
-
|
140
|
+
# Assign model attributes, using fetch. Differenct between assign_attributes and fetch_with_attributes is
|
141
|
+
# ths you can create method named fetch_:attribute and it will be used to assign attribute only on fetch.
|
142
|
+
#
|
143
|
+
# @example
|
144
|
+
# class User < Prime::Model
|
145
|
+
# attribute :created_at
|
146
|
+
# def fetch_created_at(value)
|
147
|
+
# self.created_at = Date.parse(value)
|
148
|
+
# end
|
149
|
+
# end
|
150
|
+
# user = User.new
|
151
|
+
# user.fetch_with_attributes(created_at: '2007-03-01T13:00:00Z')
|
152
|
+
# user.created_at # => 2007-03-01 13:00:00 UTC
|
153
|
+
#
|
154
|
+
# @params attributes [Hash] attributes to be assigned
|
155
|
+
# @params options [Hash] options
|
156
|
+
# @option options [Boolean] :save_associations Save included to hash associations
|
157
|
+
# @return model [Prime::Model] the model
|
158
|
+
def fetch_with_attributes(attrs, options = {})
|
114
159
|
track_changed_attributes do
|
115
160
|
attrs.each do |key, value|
|
116
161
|
if respond_to?(:"fetch_#{key}")
|
117
162
|
self.send(:"fetch_#{key}", value)
|
118
163
|
elsif has_association?(key) && (value.is_a?(Hash) || value.is_a?(Array))
|
119
|
-
should_save =
|
164
|
+
should_save = options[:save_associations]
|
120
165
|
fetch_association_with_attributes(key, value, save: should_save)
|
121
166
|
elsif respond_to?(:"#{key}=")
|
122
167
|
self.send(:"#{key}=", value)
|
@@ -189,7 +234,7 @@ module MotionPrime
|
|
189
234
|
def fetch_has_many_with_attributes(key, data, sync_options = {})
|
190
235
|
old_collection = self.send(key)
|
191
236
|
model_class = key.classify.constantize
|
192
|
-
self.
|
237
|
+
self.store.save_interval = data.count
|
193
238
|
# Update/Create existing records
|
194
239
|
data.each do |attributes|
|
195
240
|
model = old_collection.detect{ |model| model.id == attributes[:id]}
|
@@ -207,7 +252,7 @@ module MotionPrime
|
|
207
252
|
end
|
208
253
|
end
|
209
254
|
save if sync_options[:save]
|
210
|
-
self.
|
255
|
+
self.store.save_interval = 1
|
211
256
|
end
|
212
257
|
|
213
258
|
def fetch_has_one(key, options = {}, &block)
|
@@ -271,6 +316,14 @@ module MotionPrime
|
|
271
316
|
end
|
272
317
|
|
273
318
|
module ClassMethods
|
319
|
+
def fetch_all_with_attributes(data)
|
320
|
+
data.map do |attrs|
|
321
|
+
item = self.new
|
322
|
+
item.fetch_with_attributes(attrs)
|
323
|
+
item
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
274
327
|
def new(data = {}, options = {})
|
275
328
|
model = super
|
276
329
|
if fetch_attributes = options[:fetch_attributes]
|
@@ -71,12 +71,17 @@ module MotionPrime
|
|
71
71
|
set_callback :render, :after, method_name
|
72
72
|
end
|
73
73
|
def create_with_options(screen, navigation = true, options = {})
|
74
|
+
screen = create_tab_bar(screen, options) if screen.is_a?(Array)
|
74
75
|
if screen.is_a?(Symbol)
|
75
76
|
options[:navigation] = navigation unless options.has_key?(:navigation)
|
76
77
|
screen = class_factory("#{screen}_screen").new(options)
|
77
78
|
end
|
78
79
|
screen
|
79
80
|
end
|
81
|
+
|
82
|
+
def create_tab_bar(screens, options = {})
|
83
|
+
MotionPrime::TabBarController.new(screens, options)
|
84
|
+
end
|
80
85
|
end
|
81
86
|
end
|
82
87
|
end
|
@@ -14,7 +14,7 @@ module MotionPrime
|
|
14
14
|
screen.send(:on_screen_load) if screen.respond_to?(:on_screen_load)
|
15
15
|
args[:animated] = args.has_key?(:animated) ? args[:animated] : true
|
16
16
|
if args[:modal] || !has_navigation?
|
17
|
-
open_screen_modal(screen, args)
|
17
|
+
open_screen_modal(screen, args.merge(modal: true))
|
18
18
|
else
|
19
19
|
open_screen_navigational(screen, args)
|
20
20
|
end
|
@@ -36,12 +36,18 @@ module MotionPrime
|
|
36
36
|
close_screen
|
37
37
|
end
|
38
38
|
|
39
|
-
def send_on_return
|
39
|
+
def send_on_return
|
40
40
|
if parent_screen && parent_screen.respond_to?(:on_return)
|
41
41
|
parent_screen.send(:on_return)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
def send_on_leave
|
46
|
+
if respond_to?(:on_leave)
|
47
|
+
on_leave
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
45
51
|
def wrap_in_navigation?
|
46
52
|
options[:navigation] || options[:navigation].nil?
|
47
53
|
end
|
@@ -66,30 +72,26 @@ module MotionPrime
|
|
66
72
|
|
67
73
|
private
|
68
74
|
def setup_screen_for_open(screen, args = {})
|
69
|
-
|
70
|
-
screen = Screen.create_with_options(screen, true, args)
|
71
|
-
|
72
|
-
# Set parent, title & modal properties
|
75
|
+
screen = self.class.create_with_options(screen, true, args)
|
73
76
|
screen.parent_screen = self if screen.respond_to?("parent_screen=")
|
74
|
-
screen.title = args[:title] if args[:title] && screen.respond_to?("title=")
|
75
|
-
screen.modal = args[:modal] if args[:modal] && screen.respond_to?("modal=")
|
76
|
-
|
77
|
-
# Return modified screen instance
|
78
77
|
screen
|
79
78
|
end
|
80
79
|
|
81
80
|
def open_screen_modal(screen, args)
|
81
|
+
screen.modal = true if screen.respond_to?("modal=")
|
82
82
|
self.presentModalViewController(screen.main_controller, animated: args[:animated])
|
83
|
+
send_on_leave
|
83
84
|
end
|
84
85
|
|
85
86
|
def open_screen_navigational(screen, args = {})
|
86
87
|
navigation_controller.pushViewController(screen, animated: args[:animated])
|
88
|
+
send_on_leave
|
87
89
|
end
|
88
90
|
|
89
91
|
# @return screen [Prime::Screen] screen appearing after close
|
90
92
|
def close_screen_modal(args = {})
|
91
93
|
parent_screen.dismissViewControllerAnimated(args[:animated], completion: lambda {
|
92
|
-
send_on_return
|
94
|
+
send_on_return
|
93
95
|
})
|
94
96
|
parent_screen
|
95
97
|
end
|
@@ -111,7 +113,7 @@ module MotionPrime
|
|
111
113
|
result = self.navigation_controller.childViewControllers.last
|
112
114
|
end
|
113
115
|
end
|
114
|
-
send_on_return
|
116
|
+
send_on_return
|
115
117
|
result
|
116
118
|
end
|
117
119
|
|
@@ -46,23 +46,60 @@ module MotionPrime
|
|
46
46
|
options[:container_bounds] or raise "You must pass `container bounds` option to prerender base section"
|
47
47
|
end
|
48
48
|
|
49
|
+
# Get computed container options
|
50
|
+
#
|
51
|
+
# @return options [Hash] computed options
|
49
52
|
def container_options
|
50
53
|
compute_container_options! unless @container_options
|
51
54
|
@container_options
|
52
55
|
end
|
53
56
|
|
57
|
+
# Get computed container height
|
58
|
+
#
|
59
|
+
# @example
|
60
|
+
# class MySection < Prime::Section
|
61
|
+
# container height: proc { element(:title).content_outer_height }
|
62
|
+
# element :title, text: 'Hello world'
|
63
|
+
# end
|
64
|
+
# section = MySection.new
|
65
|
+
# section.container_height # => 46
|
66
|
+
#
|
67
|
+
# @return height [Float, Integer] computed height
|
54
68
|
def container_height
|
55
69
|
container_options[:height] || DEFAULT_CONTENT_HEIGHT
|
56
70
|
end
|
57
71
|
|
72
|
+
# Get section default name, based on class name
|
73
|
+
#
|
74
|
+
# @example
|
75
|
+
# class ProfileSection < Prime::Section
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# section = ProfileSection.new
|
79
|
+
# section.default_name # => 'profile'
|
80
|
+
# section.name # => 'profile'
|
81
|
+
#
|
82
|
+
# another_section = ProfileSection.new(name: 'another')
|
83
|
+
# another_section.default_name # => 'profile'
|
84
|
+
# another_section.name # => 'another'
|
85
|
+
#
|
86
|
+
# @return name [String] section default name
|
58
87
|
def default_name
|
59
88
|
self.class_name_without_kvo.demodulize.underscore.gsub(/\_section$/, '')
|
60
89
|
end
|
61
90
|
|
91
|
+
# Get section elements options, where the key is element name.
|
92
|
+
#
|
93
|
+
# @return options [Hash] elements options
|
62
94
|
def elements_options
|
63
95
|
self.class.elements_options || {}
|
64
96
|
end
|
65
97
|
|
98
|
+
# Create elements if they are not created yet.
|
99
|
+
# This will not cause rendering elements,
|
100
|
+
# they will be rendered immediately after that or rendered async later, based on type of section.
|
101
|
+
#
|
102
|
+
# @return result [Boolean] true if has been loaded by this thread.
|
66
103
|
def load_section
|
67
104
|
return if @section_loaded
|
68
105
|
if @section_loading
|
@@ -75,11 +112,16 @@ module MotionPrime
|
|
75
112
|
return @section_loaded = true
|
76
113
|
end
|
77
114
|
|
115
|
+
# Force load section
|
116
|
+
#
|
117
|
+
# @return result [Boolean] true if has been loaded by this thread.
|
78
118
|
def load_section!
|
79
119
|
@section_loaded = false
|
80
120
|
load_section
|
81
121
|
end
|
82
122
|
|
123
|
+
# Force reload section, will also re-render elements.
|
124
|
+
# For table view cells will also reload it's table data.
|
83
125
|
def reload_section
|
84
126
|
self.elements_to_render.values.map(&:view).flatten.each do |view|
|
85
127
|
view.removeFromSuperview if view
|
@@ -243,6 +243,9 @@ module MotionPrime
|
|
243
243
|
display_pending_cells
|
244
244
|
end
|
245
245
|
|
246
|
+
def scroll_view_did_scroll(scroll)
|
247
|
+
end
|
248
|
+
|
246
249
|
def scroll_view_did_end_dragging(scroll, willDecelerate: will_decelerate)
|
247
250
|
display_pending_cells unless @decelerating = will_decelerate
|
248
251
|
end
|
@@ -55,6 +55,10 @@ module MotionPrime
|
|
55
55
|
table_section.height_for_header_in_section(table, section)
|
56
56
|
end
|
57
57
|
|
58
|
+
def scrollViewDidScroll(scroll)
|
59
|
+
table_section.scroll_view_did_scroll(scroll)
|
60
|
+
end
|
61
|
+
|
58
62
|
def scrollViewWillBeginDragging(scroll)
|
59
63
|
table_section.scroll_view_will_begin_dragging(scroll)
|
60
64
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
class TabBarController < UITabBarController
|
3
|
-
def self.new(screens)
|
3
|
+
def self.new(screens, global_options = {})
|
4
4
|
controller = alloc.init
|
5
5
|
|
6
6
|
view_controllers = []
|
7
7
|
|
8
8
|
screens.each_with_index do |options, index|
|
9
9
|
if options.is_a?(Hash)
|
10
|
-
screen = init_screen_with_options(options, tag: index)
|
10
|
+
screen = init_screen_with_options(global_options.merge(options), tag: index)
|
11
11
|
else
|
12
12
|
screen = options
|
13
13
|
screen.tabBarItem.tag = index
|
@@ -33,10 +33,9 @@ module MotionPrime
|
|
33
33
|
|
34
34
|
protected
|
35
35
|
def self.init_screen_with_options(options, tag: tag)
|
36
|
-
screen, image, title = options
|
37
|
-
screen = Screen.create_with_options(screen).try(:weak_ref)
|
36
|
+
screen, image, title = options.delete(:screen), options.delete(:title)
|
37
|
+
screen = Screen.create_with_options(screen, true, options).try(:weak_ref)
|
38
38
|
title ||= screen.title
|
39
|
-
|
40
39
|
image = extract_image_from_options(options, with_key: :image)
|
41
40
|
screen.tabBarItem = UITabBarItem.alloc.initWithTitle title, image: image, tag: tag
|
42
41
|
|
@@ -46,7 +45,7 @@ module MotionPrime
|
|
46
45
|
end
|
47
46
|
|
48
47
|
def self.extract_image_from_options(options, with_key: key)
|
49
|
-
image = options
|
48
|
+
image = options.delete(key)
|
50
49
|
return unless image
|
51
50
|
image = image.uiimage
|
52
51
|
if options[:translucent] === false
|
data/motion-prime/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motion-prime
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Iskander Haziev
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-01-
|
12
|
+
date: 2014-01-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|