motion-prime 0.4.5 → 0.5.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 +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
|