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.
Files changed (88) hide show
  1. checksums.yaml +14 -6
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +14 -0
  4. data/Gemfile.lock +1 -1
  5. data/README.md +10 -8
  6. data/ROADMAP.md +9 -10
  7. data/Rakefile +1 -1
  8. data/doc/code/getting_started.rb +3 -3
  9. data/doc/code/screens.rb +25 -10
  10. data/doc/code/sections.rb +41 -0
  11. data/doc/docs/getting_started.html +8 -3
  12. data/doc/docs/screens.html +58 -19
  13. data/doc/docs/sections.html +134 -0
  14. data/files/Gemfile +7 -1
  15. data/files/Gemfile.lock +18 -9
  16. data/files/Rakefile +2 -11
  17. data/files/app/app_delegate.rb +2 -2
  18. data/files/app/config/base.rb +0 -4
  19. data/files/app/screens/application_screen.rb +2 -2
  20. data/files/app/screens/home_screen.rb +2 -0
  21. data/files/app/screens/sidebar_screen.rb +3 -3
  22. data/files/app/sections/home/section.rb +3 -0
  23. data/files/app/sections/sidebar/action.rb +1 -1
  24. data/files/app/styles/home.rb +9 -0
  25. data/files/app/styles/sidebar.rb +3 -3
  26. data/lib/motion-prime.rb +9 -0
  27. data/motion-prime/api_client.rb +5 -1
  28. data/motion-prime/app_delegate.rb +40 -45
  29. data/motion-prime/core_ext/kernel.rb +8 -0
  30. data/motion-prime/elements/_content_text_mixin.rb +3 -1
  31. data/motion-prime/elements/_text_mixin.rb +1 -1
  32. data/motion-prime/elements/base_element.rb +6 -5
  33. data/motion-prime/elements/draw/image.rb +6 -1
  34. data/motion-prime/elements/view_with_section.rb +7 -0
  35. data/motion-prime/helpers/has_style_chain_builder.rb +4 -1
  36. data/motion-prime/models/_association_mixin.rb +139 -0
  37. data/motion-prime/models/_base_mixin.rb +184 -0
  38. data/motion-prime/models/_dirty_mixin.rb +31 -0
  39. data/motion-prime/models/_finder_mixin.rb +208 -0
  40. data/motion-prime/models/{bag.rb → _nano_bag_mixin.rb} +4 -4
  41. data/motion-prime/models/{sync.rb → _sync_mixin.rb} +75 -76
  42. data/motion-prime/models/json.rb +6 -9
  43. data/motion-prime/models/model.rb +24 -172
  44. data/motion-prime/{mp.rb → prime.rb} +0 -1
  45. data/motion-prime/screens/_base_mixin.rb +9 -10
  46. data/motion-prime/screens/_navigation_mixin.rb +12 -17
  47. data/motion-prime/screens/extensions/_indicators_mixin.rb +1 -1
  48. data/motion-prime/screens/extensions/_navigation_bar_mixin.rb +3 -3
  49. data/motion-prime/screens/{base_screen.rb → screen.rb} +11 -5
  50. data/motion-prime/sections/_cell_section_mixin.rb +13 -0
  51. data/motion-prime/sections/_draw_section_mixin.rb +17 -0
  52. data/motion-prime/sections/base_section.rb +51 -16
  53. data/motion-prime/sections/form/base_field_section.rb +27 -16
  54. data/motion-prime/sections/form/base_header_section.rb +4 -3
  55. data/motion-prime/sections/form/password_field_section.rb +4 -0
  56. data/motion-prime/sections/form/select_field_section.rb +4 -0
  57. data/motion-prime/sections/form/string_field_section.rb +4 -0
  58. data/motion-prime/sections/form/submit_field_section.rb +4 -0
  59. data/motion-prime/sections/form/text_field_section.rb +4 -0
  60. data/motion-prime/sections/form.rb +7 -1
  61. data/motion-prime/sections/tabbed.rb +1 -1
  62. data/motion-prime/sections/table/table_delegate.rb +5 -0
  63. data/motion-prime/sections/table.rb +71 -51
  64. data/motion-prime/services/logger.rb +37 -0
  65. data/motion-prime/support/mp_cell_with_section.rb +9 -4
  66. data/motion-prime/support/tab_bar_controller.rb +2 -1
  67. data/motion-prime/version.rb +1 -1
  68. data/motion-prime/views/layout.rb +1 -1
  69. data/motion-prime/views/view_builder.rb +7 -0
  70. data/motion-prime.gemspec +1 -1
  71. data/spec/delegate/{base_delegate_spec.rb → delegate_spec.rb} +1 -1
  72. data/spec/helpers/{base_delegate.rb → delegates.rb} +0 -0
  73. data/spec/helpers/models.rb +11 -18
  74. data/spec/helpers/{base_screen.rb → screens.rb} +1 -1
  75. data/spec/models/{association_spec.rb → associations_spec.rb} +1 -1
  76. data/spec/models/bag_spec.rb +1 -1
  77. data/spec/models/errors_spec.rb +1 -1
  78. data/spec/models/finder_spec.rb +1 -1
  79. data/spec/models/json.rb +87 -0
  80. data/spec/models/model_spec.rb +23 -3
  81. data/spec/models/store_extension_spec.rb +1 -1
  82. data/spec/models/store_spec.rb +1 -1
  83. data/spec/screens/{base_screen_spec.rb → screen_spec.rb} +5 -1
  84. metadata +52 -43
  85. data/motion-prime/models/association.rb +0 -134
  86. data/motion-prime/models/base.rb +0 -27
  87. data/motion-prime/models/finder.rb +0 -202
  88. data/motion-prime/screens/sidebar_container_screen.rb +0 -80
@@ -1,5 +1,7 @@
1
1
  module MotionPrime
2
- module ModelSyncMethods
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
- # sync with server and save on local
25
- def sync!(sync_options = {}, &block)
26
- sync(sync_options.merge(save: true), &block)
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
- # sync with with server
30
- # TODO: order of fetch/update should be based on updated time?
31
- def sync(sync_options = {}, &block)
31
+ # fetch from server
32
+ def fetch(options = {}, &block)
32
33
  use_callback = block_given?
33
- should_fetch = sync_options[:fetch]
34
- should_update = sync_options[:update]
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
- should_fetch = persisted? if should_fetch.nil?
42
- should_update ||= new_record? unless should_fetch
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 sync_options[:save]
59
- block.call(data, status_code, data) if use_callback
60
- end if should_fetch
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
- update_with_url url, sync_options do |data, status_code|
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 && !should_fetch
66
- end if should_update
47
+ block.call(data, status_code, data) if use_callback
48
+ end if will_fetch_associations
49
+ end
67
50
 
68
- fetch_associations(sync_options) do |data, status_code|
69
- # run callback only if it wasn't run on fetch or update
70
- block.call(data, status_code, data) if use_callback && !should_fetch && !should_update
71
- end if should_fetch_associations
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, sync_options = nil, &block)
79
+ def update_with_url(url, options = {}, &block)
85
80
  use_callback = block_given?
86
- filtered_attributes = filtered_updatable_attributes(sync_options)
81
+ filtered_attributes = filtered_updatable_attributes(options)
87
82
 
88
- post_data = sync_options[:params_root] || {}
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 = sync_options[:method] || (id ? :put : :post)
90
+ method = options[:method] || (persisted? ? :put : :post)
96
91
  api_client.send(method, url, post_data) do |data, status_code|
97
- update_from_response = sync_options.has_key?(:update_from_response) ? sync_options[:update_from_response] : true
98
- if update_from_response && status_code.to_s =~ /20\d/ && data.is_a?(Hash)
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
- attrs.each do |key, value|
113
- if respond_to?(:"fetch_#{key}")
114
- self.send(:"fetch_#{key}", value)
115
- elsif respond_to?(:"#{key}=")
116
- self.send(:"#{key}=", value)
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 = key.classify.constantize.new
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
- module ModelSyncClassMethods
244
- def new(data = {}, options = {})
245
- model = super
246
- if fetch_attributes = options[:fetch_attributes]
247
- model.fetch_with_attributes(fetch_attributes)
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
- def sync_url(url = nil, &block)
253
- if url || block_given?
254
- self._sync_url = url || block
255
- else
256
- self._sync_url
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
- def updatable_attributes(*attrs)
261
- return self._updatable_attributes if attrs.blank?
262
- attrs.each do |attribute|
263
- updatable_attribute attribute
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
- def updatable_attribute(attribute, options = {}, &block)
268
- options[:block] = block if block_given?
269
- self._updatable_attributes ||= {}
270
- self._updatable_attributes[attribute] = options
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
@@ -1,12 +1,13 @@
1
1
  module MotionPrime
2
- module JSON
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 [ParserError] If the parsing of the passed string/data isn't valid.
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 ParserError, error[0].description if error[0]
18
- if block_given?
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
- module ModelMethods
3
- def self.included(base)
4
- base.class_attribute :default_sort_options
5
- end
6
-
7
- def save
8
- raise StoreError, 'No store provided' unless self.store
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
- def inspect
66
- "#<#{self.class}:0x#{self.object_id.to_s(16)}> " + MotionPrime::JSON.generate(info)
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
- if options[:type].to_s == 'boolean'
126
- define_method("#{name}?") do
127
- !!self.info[name]
128
- end
129
- end
22
+ def errors
23
+ @errors ||= Errors.new(self.weak_ref)
130
24
  end
131
25
 
132
- # Return all model attribute names
133
- #
134
- # @return Array array of attribute names
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
@@ -15,5 +15,4 @@ module MotionPrime
15
15
  ENV['PRIME_ENV'] || ENV['RUBYMOTION_ENV'] || 'development'
16
16
  end
17
17
  end
18
- ::MP = MotionPrime unless defined?(::MP)
19
18
  ::Prime = MotionPrime unless defined?(::Prime)
@@ -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::BaseScreen] Ready to use screen
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::BaseScreen] Screen to be opened
9
+ # @param screen [MotionPrime::Screen] Screen to be opened
10
10
  # @param args [Hash] Options for opening screen
11
- # @return [MotionPrime::BaseScreen]
11
+ # @return [MotionPrime::Screen]
12
12
  def open_screen(screen, args = {})
13
- if args[:modal] || has_navigation?
14
- screen = setup_screen_for_open(screen, args)
15
- screen.send(:on_screen_load) if screen.respond_to?(:on_screen_load)
16
- args[:animated] = args.has_key?(:animated) ? args[:animated] : true
17
- if args[:modal] || !has_navigation?
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
- app_delegate.open_screen(screen.main_controller)
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.new if screen.respond_to?(:new)
69
+ screen = Screen.create_with_options(screen, true, args)
75
70
 
76
71
  # Set parent, title & modal properties
77
- screen.parent_screen = self.weak_ref if screen.respond_to?("parent_screen=")
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].weak_ref
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 - 50)
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?(MotionPrime::SidebarContainerScreen)
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 BaseScreen < MPViewController
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
- # def dealloc
38
- # pp 'Deallocating Screen'
39
- # super
40
- # end
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