motion-prime 0.4.5 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +14 -6
- data/.gitignore +1 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile.lock +1 -1
- data/README.md +10 -8
- data/ROADMAP.md +9 -10
- data/Rakefile +1 -1
- data/doc/code/getting_started.rb +3 -3
- data/doc/code/screens.rb +25 -10
- data/doc/code/sections.rb +41 -0
- data/doc/docs/getting_started.html +8 -3
- data/doc/docs/screens.html +58 -19
- data/doc/docs/sections.html +134 -0
- data/files/Gemfile +7 -1
- data/files/Gemfile.lock +18 -9
- data/files/Rakefile +2 -11
- data/files/app/app_delegate.rb +2 -2
- data/files/app/config/base.rb +0 -4
- data/files/app/screens/application_screen.rb +2 -2
- data/files/app/screens/home_screen.rb +2 -0
- data/files/app/screens/sidebar_screen.rb +3 -3
- data/files/app/sections/home/section.rb +3 -0
- data/files/app/sections/sidebar/action.rb +1 -1
- data/files/app/styles/home.rb +9 -0
- data/files/app/styles/sidebar.rb +3 -3
- data/lib/motion-prime.rb +9 -0
- data/motion-prime/api_client.rb +5 -1
- data/motion-prime/app_delegate.rb +40 -45
- data/motion-prime/core_ext/kernel.rb +8 -0
- data/motion-prime/elements/_content_text_mixin.rb +3 -1
- data/motion-prime/elements/_text_mixin.rb +1 -1
- data/motion-prime/elements/base_element.rb +6 -5
- data/motion-prime/elements/draw/image.rb +6 -1
- data/motion-prime/elements/view_with_section.rb +7 -0
- data/motion-prime/helpers/has_style_chain_builder.rb +4 -1
- data/motion-prime/models/_association_mixin.rb +139 -0
- data/motion-prime/models/_base_mixin.rb +184 -0
- data/motion-prime/models/_dirty_mixin.rb +31 -0
- data/motion-prime/models/_finder_mixin.rb +208 -0
- data/motion-prime/models/{bag.rb → _nano_bag_mixin.rb} +4 -4
- data/motion-prime/models/{sync.rb → _sync_mixin.rb} +75 -76
- data/motion-prime/models/json.rb +6 -9
- data/motion-prime/models/model.rb +24 -172
- data/motion-prime/{mp.rb → prime.rb} +0 -1
- data/motion-prime/screens/_base_mixin.rb +9 -10
- data/motion-prime/screens/_navigation_mixin.rb +12 -17
- data/motion-prime/screens/extensions/_indicators_mixin.rb +1 -1
- data/motion-prime/screens/extensions/_navigation_bar_mixin.rb +3 -3
- data/motion-prime/screens/{base_screen.rb → screen.rb} +11 -5
- data/motion-prime/sections/_cell_section_mixin.rb +13 -0
- data/motion-prime/sections/_draw_section_mixin.rb +17 -0
- data/motion-prime/sections/base_section.rb +51 -16
- data/motion-prime/sections/form/base_field_section.rb +27 -16
- data/motion-prime/sections/form/base_header_section.rb +4 -3
- data/motion-prime/sections/form/password_field_section.rb +4 -0
- data/motion-prime/sections/form/select_field_section.rb +4 -0
- data/motion-prime/sections/form/string_field_section.rb +4 -0
- data/motion-prime/sections/form/submit_field_section.rb +4 -0
- data/motion-prime/sections/form/text_field_section.rb +4 -0
- data/motion-prime/sections/form.rb +7 -1
- data/motion-prime/sections/tabbed.rb +1 -1
- data/motion-prime/sections/table/table_delegate.rb +5 -0
- data/motion-prime/sections/table.rb +71 -51
- data/motion-prime/services/logger.rb +37 -0
- data/motion-prime/support/mp_cell_with_section.rb +9 -4
- data/motion-prime/support/tab_bar_controller.rb +2 -1
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/layout.rb +1 -1
- data/motion-prime/views/view_builder.rb +7 -0
- data/motion-prime.gemspec +1 -1
- data/spec/delegate/{base_delegate_spec.rb → delegate_spec.rb} +1 -1
- data/spec/helpers/{base_delegate.rb → delegates.rb} +0 -0
- data/spec/helpers/models.rb +11 -18
- data/spec/helpers/{base_screen.rb → screens.rb} +1 -1
- data/spec/models/{association_spec.rb → associations_spec.rb} +1 -1
- data/spec/models/bag_spec.rb +1 -1
- data/spec/models/errors_spec.rb +1 -1
- data/spec/models/finder_spec.rb +1 -1
- data/spec/models/json.rb +87 -0
- data/spec/models/model_spec.rb +23 -3
- data/spec/models/store_extension_spec.rb +1 -1
- data/spec/models/store_spec.rb +1 -1
- data/spec/screens/{base_screen_spec.rb → screen_spec.rb} +5 -1
- metadata +52 -43
- data/motion-prime/models/association.rb +0 -134
- data/motion-prime/models/base.rb +0 -27
- data/motion-prime/models/finder.rb +0 -202
- data/motion-prime/screens/sidebar_container_screen.rb +0 -80
@@ -1,5 +1,7 @@
|
|
1
1
|
module MotionPrime
|
2
|
-
module
|
2
|
+
module ModelSyncMixin
|
3
|
+
extend ::MotionSupport::Concern
|
4
|
+
|
3
5
|
def self.included(base)
|
4
6
|
base.class_attribute :_sync_url
|
5
7
|
base.class_attribute :_updatable_attributes
|
@@ -21,54 +23,47 @@ module MotionPrime
|
|
21
23
|
delete
|
22
24
|
end
|
23
25
|
|
24
|
-
#
|
25
|
-
def
|
26
|
-
|
26
|
+
# fetch from server and save on local
|
27
|
+
def fetch!(options = {}, &block)
|
28
|
+
fetch(options.merge(save: true), &block)
|
27
29
|
end
|
28
30
|
|
29
|
-
#
|
30
|
-
|
31
|
-
def sync(sync_options = {}, &block)
|
31
|
+
# fetch from server
|
32
|
+
def fetch(options = {}, &block)
|
32
33
|
use_callback = block_given?
|
33
|
-
|
34
|
-
|
35
|
-
should_fetch_associations = if sync_options.has_key?(:fetch_associations)
|
36
|
-
sync_options[:fetch_associations]
|
37
|
-
else # do not need to fetch unless this is a GET request
|
38
|
-
should_fetch
|
39
|
-
end
|
34
|
+
method = options[:method] || :get
|
35
|
+
url = sync_url(method, options)
|
40
36
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
method = sync_options[:method]
|
45
|
-
method ||= if should_update
|
46
|
-
persisted? ? :put : :post
|
47
|
-
else
|
48
|
-
:get
|
49
|
-
end
|
50
|
-
url = sync_url(method, sync_options)
|
51
|
-
|
52
|
-
if url.blank?
|
53
|
-
should_fetch = false
|
54
|
-
should_update = false
|
55
|
-
end
|
37
|
+
will_fetch_model = !url.blank?
|
38
|
+
will_fetch_associations = !options.has_key?(:associations) || options[:associations]
|
56
39
|
|
57
40
|
fetch_with_url url do |data, status_code|
|
58
|
-
save if
|
59
|
-
block.call(data, status_code, data) if use_callback
|
60
|
-
end if
|
41
|
+
save if options[:save]
|
42
|
+
block.call(data, status_code, data) if use_callback && !will_fetch_associations
|
43
|
+
end if will_fetch_model
|
61
44
|
|
62
|
-
|
63
|
-
save if sync_options[:save] && status_code.to_s =~ /20\d/
|
45
|
+
fetch_associations(options) do |data, status_code|
|
64
46
|
# run callback only if it wasn't run on fetch
|
65
|
-
block.call(data, status_code, data) if use_callback
|
66
|
-
end if
|
47
|
+
block.call(data, status_code, data) if use_callback
|
48
|
+
end if will_fetch_associations
|
49
|
+
end
|
67
50
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
51
|
+
# update on server and save response on local
|
52
|
+
def update!(options = {}, &block)
|
53
|
+
update(options.merge(save_response: true), &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
# update on server
|
57
|
+
def update(options = {}, &block)
|
58
|
+
use_callback = block_given?
|
59
|
+
|
60
|
+
method = options[:method] || (persisted? ? :put : :post)
|
61
|
+
url = sync_url(method, options)
|
62
|
+
will_update_model = !url.blank?
|
63
|
+
|
64
|
+
update_with_url url, options do |data, status_code|
|
65
|
+
block.call(data, status_code, data) if use_callback
|
66
|
+
end if will_update_model
|
72
67
|
end
|
73
68
|
|
74
69
|
# fetch from server using url
|
@@ -81,22 +76,23 @@ module MotionPrime
|
|
81
76
|
end
|
82
77
|
|
83
78
|
# update on server using url
|
84
|
-
def update_with_url(url,
|
79
|
+
def update_with_url(url, options = {}, &block)
|
85
80
|
use_callback = block_given?
|
86
|
-
filtered_attributes = filtered_updatable_attributes(
|
81
|
+
filtered_attributes = filtered_updatable_attributes(options)
|
87
82
|
|
88
|
-
post_data =
|
83
|
+
post_data = options[:params_root] || {}
|
89
84
|
post_data[:files] = {}
|
90
85
|
filtered_attributes.delete(:files).each do |file_name, file|
|
91
86
|
post_data[:files][[model_name, file_name].join] = file
|
92
87
|
end
|
93
88
|
post_data[model_name] = filtered_attributes
|
94
89
|
|
95
|
-
method =
|
90
|
+
method = options[:method] || (persisted? ? :put : :post)
|
96
91
|
api_client.send(method, url, post_data) do |data, status_code|
|
97
|
-
|
98
|
-
if
|
92
|
+
save_response = !options.has_key?(:save_response) || options[:save_response]
|
93
|
+
if save_response && status_code.to_s =~ /20\d/ && data.is_a?(Hash)
|
99
94
|
set_attributes_from_response(data)
|
95
|
+
save
|
100
96
|
end
|
101
97
|
block.call(data, status_code, data) if use_callback
|
102
98
|
end
|
@@ -109,11 +105,13 @@ module MotionPrime
|
|
109
105
|
|
110
106
|
# set attributes, using fetch
|
111
107
|
def fetch_with_attributes(attrs)
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
108
|
+
track_changed_attributes do
|
109
|
+
attrs.each do |key, value|
|
110
|
+
if respond_to?(:"fetch_#{key}")
|
111
|
+
self.send(:"fetch_#{key}", value)
|
112
|
+
elsif respond_to?(:"#{key}=")
|
113
|
+
self.send(:"#{key}=", value)
|
114
|
+
end
|
117
115
|
end
|
118
116
|
end
|
119
117
|
self
|
@@ -156,16 +154,17 @@ module MotionPrime
|
|
156
154
|
NSLog("SYNC: started sync for #{key} in #{self.class_name_without_kvo}")
|
157
155
|
api_client.get normalize_sync_url(options[:sync_url]) do |response, status_code|
|
158
156
|
data = options[:sync_key] && response ? response[options[:sync_key]] : response
|
157
|
+
model_class = key.classify.constantize
|
159
158
|
if data
|
160
159
|
# Update/Create existing records
|
161
160
|
data.each do |attributes|
|
162
161
|
model = old_collection.detect{ |model| model.id == attributes[:id]}
|
163
162
|
unless model
|
164
|
-
model =
|
163
|
+
model = model_class.new
|
165
164
|
self.send(:"#{key}_bag") << model
|
166
165
|
end
|
167
166
|
model.fetch_with_attributes(attributes)
|
168
|
-
model.save if sync_options[:save]
|
167
|
+
model.save if sync_options[:save] && model.has_changed?
|
169
168
|
end
|
170
169
|
old_collection.each do |old_model|
|
171
170
|
model = data.detect{ |model| model[:id] == old_model.id}
|
@@ -238,36 +237,36 @@ module MotionPrime
|
|
238
237
|
def normalize_sync_url(url)
|
239
238
|
url.to_s.gsub(':id', id.to_s)
|
240
239
|
end
|
241
|
-
end
|
242
240
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
241
|
+
module ClassMethods
|
242
|
+
def new(data = {}, options = {})
|
243
|
+
model = super
|
244
|
+
if fetch_attributes = options[:fetch_attributes]
|
245
|
+
model.fetch_with_attributes(fetch_attributes)
|
246
|
+
end
|
247
|
+
model
|
248
248
|
end
|
249
|
-
model
|
250
|
-
end
|
251
249
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
250
|
+
def sync_url(url = nil, &block)
|
251
|
+
if url || block_given?
|
252
|
+
self._sync_url = url || block
|
253
|
+
else
|
254
|
+
self._sync_url
|
255
|
+
end
|
257
256
|
end
|
258
|
-
end
|
259
257
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
258
|
+
def updatable_attributes(*attrs)
|
259
|
+
return self._updatable_attributes if attrs.blank?
|
260
|
+
attrs.each do |attribute|
|
261
|
+
updatable_attribute attribute
|
262
|
+
end
|
264
263
|
end
|
265
|
-
end
|
266
264
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
265
|
+
def updatable_attribute(attribute, options = {}, &block)
|
266
|
+
options[:block] = block if block_given?
|
267
|
+
self._updatable_attributes ||= {}
|
268
|
+
self._updatable_attributes[attribute] = options
|
269
|
+
end
|
271
270
|
end
|
272
271
|
end
|
273
272
|
end
|
data/motion-prime/models/json.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
module MotionPrime
|
2
|
-
|
2
|
+
class JsonParseError < StandardError; end
|
3
|
+
|
4
|
+
class JSON
|
3
5
|
PARAMETRIZE_CLASSES = [Time, Date]
|
4
|
-
class ParserError < StandardError; end
|
5
6
|
|
6
7
|
# Parses a string or data object and converts it in data structure.
|
7
8
|
#
|
8
9
|
# @param [String, NSData] str_data the string or data to convert.
|
9
|
-
# @raise [
|
10
|
+
# @raise [JsonParseError] If the parsing of the passed string/data isn't valid.
|
10
11
|
# @return [Hash, Array, NilClass] the converted data structure, nil if the incoming string isn't valid.
|
11
12
|
def self.parse(str_data, &block)
|
12
13
|
return nil unless str_data
|
@@ -14,12 +15,8 @@ module MotionPrime
|
|
14
15
|
opts = NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves | NSJSONReadingAllowFragments
|
15
16
|
error = Pointer.new(:id)
|
16
17
|
obj = NSJSONSerialization.JSONObjectWithData(data, options: opts, error: error)
|
17
|
-
raise
|
18
|
-
|
19
|
-
yield obj
|
20
|
-
else
|
21
|
-
obj
|
22
|
-
end
|
18
|
+
raise JsonParseError, error[0].description if error[0]
|
19
|
+
obj
|
23
20
|
end
|
24
21
|
|
25
22
|
# Generates a string from data structure.
|
@@ -1,178 +1,30 @@
|
|
1
|
+
motion_require '../helpers/has_authorization'
|
2
|
+
motion_require './_nano_bag_mixin.rb'
|
3
|
+
motion_require './_finder_mixin.rb'
|
4
|
+
motion_require './_base_mixin.rb'
|
5
|
+
motion_require './_sync_mixin.rb'
|
6
|
+
motion_require './_association_mixin.rb'
|
7
|
+
motion_require './_dirty_mixin.rb'
|
8
|
+
motion_require './store.rb'
|
9
|
+
motion_require './store_extension.rb'
|
1
10
|
module MotionPrime
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
error_ptr = Pointer.new(:id)
|
10
|
-
self.store.addObject(self, error: error_ptr)
|
11
|
-
raise StoreError, error_ptr[0].description if error_ptr[0]
|
12
|
-
self
|
13
|
-
end
|
14
|
-
|
15
|
-
def delete
|
16
|
-
raise StoreError, 'No store provided' unless self.store
|
17
|
-
|
18
|
-
error_ptr = Pointer.new(:id)
|
19
|
-
self.store.removeObject(self, error: error_ptr)
|
20
|
-
raise StoreError, error_ptr[0].description if error_ptr[0]
|
21
|
-
self
|
22
|
-
end
|
23
|
-
|
24
|
-
def store
|
25
|
-
super || self.class.store
|
26
|
-
end
|
27
|
-
|
28
|
-
def assign_attributes(new_attributes, options = {})
|
29
|
-
attributes = new_attributes.symbolize_keys
|
30
|
-
attributes.each do |k, v|
|
31
|
-
if has_attribute?(k)
|
32
|
-
assign_attribute(k, v) unless options[:skip_nil_values] && v.nil?
|
33
|
-
elsif options[:check_attribute_presence]
|
34
|
-
NSLog("unknown attribute: #{k}")
|
35
|
-
else
|
36
|
-
raise(NoMethodError, "unknown attribute: #{k}")
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def assign_attribute(name, value)
|
42
|
-
self.send("#{name}=", value) if has_attribute?(name)
|
43
|
-
end
|
44
|
-
|
45
|
-
def has_attribute?(name)
|
46
|
-
respond_to?("#{name}=")
|
47
|
-
end
|
48
|
-
|
49
|
-
def attributes_hash
|
50
|
-
self.info.to_hash.symbolize_keys
|
51
|
-
end
|
52
|
-
|
53
|
-
def new_record?
|
54
|
-
id.blank?
|
55
|
-
end
|
56
|
-
|
57
|
-
def persisted?
|
58
|
-
!new_record?
|
59
|
-
end
|
60
|
-
|
61
|
-
def model_name
|
62
|
-
self.class_name_without_kvo.underscore
|
63
|
-
end
|
11
|
+
class Model < NSFNanoObject
|
12
|
+
include MotionPrime::HasAuthorization
|
13
|
+
include MotionPrime::ModelBaseMixin
|
14
|
+
include MotionPrime::ModelAssociationMixin
|
15
|
+
include MotionPrime::ModelSyncMixin
|
16
|
+
include MotionPrime::ModelFinderMixin
|
17
|
+
include MotionPrime::ModelDirtyMixin
|
64
18
|
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
module ModelClassMethods
|
71
|
-
# Initialize a new object
|
72
|
-
#
|
73
|
-
# Examples:
|
74
|
-
# User.new(name: "Bob", age: 10)
|
75
|
-
#
|
76
|
-
# @return MotionPrime::BaseModel unsaved model
|
77
|
-
def new(data = {}, options = {})
|
78
|
-
data.keys.each { |k|
|
79
|
-
unless self.attributes.member? k.to_sym
|
80
|
-
raise StoreError, "'#{k}' is not a defined attribute for this model"
|
81
|
-
end
|
82
|
-
}
|
83
|
-
|
84
|
-
object = self.nanoObjectWithDictionary(data)
|
85
|
-
object
|
86
|
-
end
|
87
|
-
|
88
|
-
# Initialize a new object and save it
|
89
|
-
#
|
90
|
-
# Examples:
|
91
|
-
# User.create(name: "Bob", age: 10)
|
92
|
-
#
|
93
|
-
# @return MotionPrime::BaseModel saved model
|
94
|
-
def create(data = {})
|
95
|
-
object = self.new(data)
|
96
|
-
object.save
|
97
|
-
end
|
98
|
-
|
99
|
-
# Define model attribute
|
100
|
-
#
|
101
|
-
# Examples:
|
102
|
-
# class User < MotionPrime::BaseModel
|
103
|
-
# attribute :name
|
104
|
-
# attribute :age
|
105
|
-
# end
|
106
|
-
#
|
107
|
-
# @return Nil
|
108
|
-
def attribute(name, options = {})
|
109
|
-
attributes << name
|
110
|
-
|
111
|
-
define_method(name) do |*args, &block|
|
112
|
-
self.info[name]
|
113
|
-
end
|
114
|
-
|
115
|
-
define_method((name + "=").to_sym) do |*args, &block|
|
116
|
-
value = args[0]
|
117
|
-
case options[:type].to_s
|
118
|
-
when 'integer' then value = value.to_i
|
119
|
-
when 'float' then value = value.to_f
|
120
|
-
end unless value.nil?
|
121
|
-
|
122
|
-
self.info[name] = value
|
123
|
-
end
|
19
|
+
attribute :bag_key # need this as we use shared store; each nested resource must belong to parent bag
|
20
|
+
attribute :id
|
124
21
|
|
125
|
-
|
126
|
-
|
127
|
-
!!self.info[name]
|
128
|
-
end
|
129
|
-
end
|
22
|
+
def errors
|
23
|
+
@errors ||= Errors.new(self.weak_ref)
|
130
24
|
end
|
131
25
|
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
def attributes(*attrs)
|
136
|
-
if attrs.size > 0
|
137
|
-
attrs.each{|attr| attribute attr}
|
138
|
-
else
|
139
|
-
@attributes ||= []
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
# Return store associated with model class, or shared store by default
|
144
|
-
#
|
145
|
-
# @return MotionPrime::Store store
|
146
|
-
def store
|
147
|
-
@store ||= MotionPrime::Store.shared_store
|
148
|
-
end
|
149
|
-
|
150
|
-
# Define store associated with model class
|
151
|
-
#
|
152
|
-
# @param MotionPrime::Store store
|
153
|
-
# @return MotionPrime::Store store
|
154
|
-
def store=(store)
|
155
|
-
@store = store
|
156
|
-
end
|
157
|
-
|
158
|
-
# Count of models
|
159
|
-
#
|
160
|
-
# @return Fixnum count
|
161
|
-
def count
|
162
|
-
self.store.count(self)
|
163
|
-
end
|
164
|
-
|
165
|
-
# Delete objects from store
|
166
|
-
#
|
167
|
-
# @param [Array, MotionPrime::BaseModel] objects to delete
|
168
|
-
# @return [Array] result
|
169
|
-
def delete(*args)
|
170
|
-
keys = find_keys(*args)
|
171
|
-
self.store.delete_keys(keys)
|
172
|
-
end
|
173
|
-
|
174
|
-
def default_sort(sort_options)
|
175
|
-
self.default_sort_options = sort_options
|
176
|
-
end
|
26
|
+
# def dealloc
|
27
|
+
# pp 'deall model'
|
28
|
+
# end
|
177
29
|
end
|
178
|
-
end
|
30
|
+
end
|
@@ -21,23 +21,15 @@ module MotionPrime
|
|
21
21
|
UIApplication.sharedApplication.delegate
|
22
22
|
end
|
23
23
|
|
24
|
-
def show_sidebar
|
25
|
-
app_delegate.show_sidebar
|
26
|
-
end
|
27
|
-
|
28
|
-
def hide_sidebar
|
29
|
-
app_delegate.hide_sidebar
|
30
|
-
end
|
31
|
-
|
32
24
|
def on_screen_load
|
33
25
|
run_callbacks :load do
|
34
26
|
on_load
|
35
27
|
end
|
36
28
|
end
|
37
29
|
|
38
|
-
# Setup the screen, will be called when you run MPViewController.new
|
30
|
+
# Setup the screen, this method will be called when you run MPViewController.new
|
39
31
|
# @param options [hash] Options passed to setup
|
40
|
-
# @return [MotionPrime::
|
32
|
+
# @return [MotionPrime::Screen] Ready to use screen
|
41
33
|
def on_create(options = {})
|
42
34
|
unless self.is_a?(UIViewController)
|
43
35
|
raise StandardError.new("ERROR: Screens must extend UIViewController.")
|
@@ -88,6 +80,13 @@ module MotionPrime
|
|
88
80
|
def after_load(method_name)
|
89
81
|
set_callback :load, :after, method_name
|
90
82
|
end
|
83
|
+
def create_with_options(screen, navigation = true, options = {})
|
84
|
+
if screen.is_a?(Symbol)
|
85
|
+
options[:navigation] = navigation unless options.has_key?(:navigation)
|
86
|
+
screen = class_factory("#{screen}_screen").new(options)
|
87
|
+
end
|
88
|
+
screen
|
89
|
+
end
|
91
90
|
end
|
92
91
|
end
|
93
92
|
end
|
@@ -6,26 +6,21 @@ module MotionPrime
|
|
6
6
|
# animated: open screen with animation.
|
7
7
|
# modal: open screen as model
|
8
8
|
|
9
|
-
# @param screen [MotionPrime::
|
9
|
+
# @param screen [MotionPrime::Screen] Screen to be opened
|
10
10
|
# @param args [Hash] Options for opening screen
|
11
|
-
# @return [MotionPrime::
|
11
|
+
# @return [MotionPrime::Screen]
|
12
12
|
def open_screen(screen, args = {})
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
open_screen_modal(screen, args)
|
19
|
-
else
|
20
|
-
open_screen_navigational(screen, args)
|
21
|
-
end
|
13
|
+
screen = setup_screen_for_open(screen, args)
|
14
|
+
screen.send(:on_screen_load) if screen.respond_to?(:on_screen_load)
|
15
|
+
args[:animated] = args.has_key?(:animated) ? args[:animated] : true
|
16
|
+
if args[:modal] || !has_navigation?
|
17
|
+
open_screen_modal(screen, args)
|
22
18
|
else
|
23
|
-
|
19
|
+
open_screen_navigational(screen, args)
|
24
20
|
end
|
25
21
|
screen
|
26
22
|
end
|
27
23
|
|
28
|
-
|
29
24
|
def close_screen(args = {})
|
30
25
|
args[:animated] = args.has_key?(:animated) ? args[:animated] : true
|
31
26
|
# Pop current view, maybe with arguments, if in navigation controller
|
@@ -47,7 +42,7 @@ module MotionPrime
|
|
47
42
|
end
|
48
43
|
|
49
44
|
def wrap_in_navigation?
|
50
|
-
options[:navigation]
|
45
|
+
options[:navigation] || options[:navigation].nil?
|
51
46
|
end
|
52
47
|
|
53
48
|
def wrap_in_navigation
|
@@ -71,10 +66,10 @@ module MotionPrime
|
|
71
66
|
private
|
72
67
|
def setup_screen_for_open(screen, args = {})
|
73
68
|
# Instantiate screen if given a class
|
74
|
-
screen = screen
|
69
|
+
screen = Screen.create_with_options(screen, true, args)
|
75
70
|
|
76
71
|
# Set parent, title & modal properties
|
77
|
-
screen.parent_screen = self
|
72
|
+
screen.parent_screen = self if screen.respond_to?("parent_screen=")
|
78
73
|
screen.title = args[:title] if args[:title] && screen.respond_to?("title=")
|
79
74
|
screen.modal = args[:modal] if args[:modal] && screen.respond_to?("modal=")
|
80
75
|
|
@@ -98,7 +93,7 @@ module MotionPrime
|
|
98
93
|
|
99
94
|
def close_screen_navigational(args = {})
|
100
95
|
if args[:to_screen] && args[:to_screen].is_a?(UIViewController)
|
101
|
-
self.parent_screen = args[:to_screen]
|
96
|
+
self.parent_screen = args[:to_screen]
|
102
97
|
|
103
98
|
screens = self.navigation_controller.childViewControllers
|
104
99
|
self.navigation_controller.popToViewController(args[:to_screen], animated: args[:animated])
|
@@ -3,7 +3,7 @@ module MotionPrime
|
|
3
3
|
def show_activity_indicator
|
4
4
|
if @activity_indicator_view.nil?
|
5
5
|
@activity_indicator_view = UIActivityIndicatorView.gray
|
6
|
-
@activity_indicator_view.center = CGPointMake(view.center.x, view.center.y
|
6
|
+
@activity_indicator_view.center = CGPointMake(view.center.x, view.center.y)
|
7
7
|
view.addSubview @activity_indicator_view
|
8
8
|
end
|
9
9
|
@activity_indicator_view.startAnimating
|
@@ -24,8 +24,9 @@ module MotionPrime
|
|
24
24
|
navigationItem.leftBarButtonItem = create_navigation_button(title, {action: :back}.merge(args))
|
25
25
|
end
|
26
26
|
|
27
|
+
# should be extracted to sidebar gem
|
27
28
|
def set_navigation_back_or_menu(back_title = 'Back')
|
28
|
-
if parent_screen.is_a?(
|
29
|
+
if parent_screen.is_a?(PrimeResideMenu::SidebarContainerScreen)
|
29
30
|
set_navigation_left_button 'Menu', image: 'images/navigation/menu_button.png', action: :show_sidebar
|
30
31
|
else
|
31
32
|
set_navigation_back_button back_title, icon: 'images/navigation/back_icon.png'
|
@@ -41,7 +42,6 @@ module MotionPrime
|
|
41
42
|
|
42
43
|
def create_navigation_button(title, args = {})
|
43
44
|
args[:style] ||= UIBarButtonItemStylePlain
|
44
|
-
args[:target] = (args[:target] || self).weak_ref
|
45
45
|
args[:action] ||= nil
|
46
46
|
# TODO: Find better place for this code, may be just create custom control
|
47
47
|
if args[:image]
|
@@ -66,7 +66,7 @@ module MotionPrime
|
|
66
66
|
UIBarButtonItem.alloc.initWithCustomView(face)
|
67
67
|
else
|
68
68
|
UIBarButtonItem.alloc.initWithTitle(title,
|
69
|
-
style: args[:style], target: args[:target], action: args[:action])
|
69
|
+
style: args[:style], target: args[:target] || self, action: args[:action])
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -6,7 +6,7 @@ motion_require './extensions/_navigation_bar_mixin'
|
|
6
6
|
motion_require '../helpers/has_authorization'
|
7
7
|
motion_require '../helpers/has_search_bar'
|
8
8
|
module MotionPrime
|
9
|
-
class
|
9
|
+
class Screen < MPViewController
|
10
10
|
include Layout
|
11
11
|
include ScreenBaseMixin
|
12
12
|
|
@@ -18,6 +18,8 @@ module MotionPrime
|
|
18
18
|
include HasAuthorization
|
19
19
|
include HasSearchBar
|
20
20
|
|
21
|
+
extend HasClassFactory
|
22
|
+
|
21
23
|
def render
|
22
24
|
end
|
23
25
|
|
@@ -34,10 +36,14 @@ module MotionPrime
|
|
34
36
|
@on_appear_happened = true
|
35
37
|
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
def dealloc
|
40
|
+
pp 'Deallocating Screen'
|
41
|
+
@main_section.instance_variable_set(:"@break_preload", true) # TODO: find a better option
|
42
|
+
# FIXME: calling instance_eval in title method (_base_screen_mixin) instance variables need to be cleared manually
|
43
|
+
# clear_instance_variables cause BAD_ACCESS errors too
|
44
|
+
@main_section = nil
|
45
|
+
super
|
46
|
+
end
|
41
47
|
|
42
48
|
def visible?
|
43
49
|
self.isViewLoaded && view.window
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# This Mixin will be included only to sections, which added as cell to table section.
|
1
2
|
module MotionPrime
|
2
3
|
module CellSectionMixin
|
3
4
|
extend ::MotionSupport::Concern
|
@@ -35,6 +36,11 @@ module MotionPrime
|
|
35
36
|
@container_bounds ||= CGRectMake(0, 0, table.table_view.bounds.size.width, container_height)
|
36
37
|
end
|
37
38
|
|
39
|
+
# should do nothing, because table section will care about it.
|
40
|
+
def render_container(options = {}, &block)
|
41
|
+
block.call
|
42
|
+
end
|
43
|
+
|
38
44
|
def init_container_element(options = {})
|
39
45
|
@container_element ||= begin
|
40
46
|
options.merge!({
|
@@ -49,6 +55,7 @@ module MotionPrime
|
|
49
55
|
end
|
50
56
|
end
|
51
57
|
|
58
|
+
# FIXME: Why this duplicates functionality from other parts, e.g. draw_in?
|
52
59
|
def load_container_element(options = {})
|
53
60
|
init_container_element(options)
|
54
61
|
load_elements
|
@@ -68,6 +75,12 @@ module MotionPrime
|
|
68
75
|
container_view.setNeedsDisplay
|
69
76
|
end
|
70
77
|
|
78
|
+
def dealloc
|
79
|
+
# TODO: remove this when solve this problem: dealloc TableCells on TableView.reloadData (in case when reuseIdentifier has been used)
|
80
|
+
container_view.section = nil if container_view.respond_to?(:setSection)
|
81
|
+
super
|
82
|
+
end
|
83
|
+
|
71
84
|
module ClassMethods
|
72
85
|
def set_cell_name(value)
|
73
86
|
self.custom_cell_name = value
|