motion-prime 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/Gemfile.lock +1 -1
  4. data/ROADMAP.md +3 -0
  5. data/files/Gemfile +1 -1
  6. data/lib/motion-prime.rb +1 -1
  7. data/motion-prime/api_client.rb +7 -5
  8. data/motion-prime/elements/_content_text_mixin.rb +14 -4
  9. data/motion-prime/elements/_text_mixin.rb +6 -2
  10. data/motion-prime/elements/base_element.rb +37 -12
  11. data/motion-prime/elements/button.rb +1 -1
  12. data/motion-prime/elements/draw.rb +6 -0
  13. data/motion-prime/elements/draw/_draw_background_mixin.rb +33 -2
  14. data/motion-prime/elements/draw/image.rb +9 -5
  15. data/motion-prime/elements/draw/label.rb +1 -1
  16. data/motion-prime/elements/label.rb +1 -1
  17. data/motion-prime/helpers/has_normalizer.rb +2 -1
  18. data/motion-prime/helpers/has_style_options.rb +16 -0
  19. data/motion-prime/helpers/has_styles.rb +5 -1
  20. data/motion-prime/models/_association_mixin.rb +17 -2
  21. data/motion-prime/models/_base_mixin.rb +5 -1
  22. data/motion-prime/models/_dirty_mixin.rb +1 -1
  23. data/motion-prime/models/_nano_bag_mixin.rb +18 -5
  24. data/motion-prime/models/_sync_mixin.rb +3 -3
  25. data/motion-prime/models/_timestamps_mixin.rb +3 -3
  26. data/motion-prime/sections/_draw_section_mixin.rb +20 -3
  27. data/motion-prime/sections/_section_with_container_mixin.rb +1 -1
  28. data/motion-prime/sections/abstract_collection.rb +6 -2
  29. data/motion-prime/sections/base_section.rb +6 -6
  30. data/motion-prime/sections/collection/collection_delegate.rb +6 -4
  31. data/motion-prime/sections/form/base_field_section.rb +8 -0
  32. data/motion-prime/sections/page_view.rb +19 -5
  33. data/motion-prime/sections/page_view/page_view_delegate.rb +19 -6
  34. data/motion-prime/sections/table/refresh_mixin.rb +1 -1
  35. data/motion-prime/sections/table/table_delegate.rb +6 -4
  36. data/motion-prime/styles/base.rb +1 -1
  37. data/motion-prime/support/consts.rb +6 -1
  38. data/motion-prime/support/mp_table_view.rb +4 -4
  39. data/motion-prime/version.rb +1 -1
  40. data/motion-prime/views/styles.rb +1 -1
  41. data/motion-prime/views/view_builder.rb +9 -5
  42. data/motion-prime/views/view_styler.rb +16 -15
  43. metadata +37 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6b5a8d65686ce22cebae1f6a18212692367805be
4
- data.tar.gz: 3e66ba6bf3966649c60a86210fdad3165a5822a2
3
+ metadata.gz: c05d314976c62a856091891705c135ec7efcec22
4
+ data.tar.gz: c36d99bc5fbd5c2220d0eac3677d87dbc0acf4b8
5
5
  SHA512:
6
- metadata.gz: 599c6c60f50516854af50238bcbfd1e09a6d2e248e8687c9436672bbe9b7c86192d36c642e0a647da3f04667a57411df4de03aa557efec3a32511738fffad736
7
- data.tar.gz: 04eadebb2e6967e2abb9ff613bdbc1c38632ec2b907442df57c54ddcd19f3b0477ec6592093ba100cb44c5f6e91f17f769c25fbfadc39989072686ad346e4a7f
6
+ metadata.gz: 89864fab09b0b64a7c1ad1610300141c5ae60296a4a858e7abb83ceecf1277ebd3ff027886a061e1e022e1df551e9270b24f435a12f33d34973e7d4940d72e35
7
+ data.tar.gz: 6c83f9726a57b620a1d2f93fd0e8e8b2089d3e71de9f5bea27acd279f98ad9a9f536bd247d1b4fd42822cc31341510d3ce82316eba8b49314ca8a71ee7dc5829
@@ -1,3 +1,8 @@
1
+ === 1.0.4
2
+ * Multiple bug fixes
3
+ * Model#save will be performed on main thread (now you can fetch models in thread)
4
+ * Improved support for UIPageViewController
5
+
1
6
  === 1.0.3
2
7
  * Fixed issue with overriding background color
3
8
  * Improved support for UIPageViewController
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- motion-prime (1.0.3)
4
+ motion-prime (1.0.4)
5
5
  activesupport
6
6
  afmotion (~> 2.1.0)
7
7
  bubble-wrap (~> 1.6.0)
data/ROADMAP.md CHANGED
@@ -1,4 +1,5 @@
1
1
  === 1.1.0
2
+ * Model.fetch should always return status of main model fetch response
2
3
  * grid item width should be calculated based on uicollectionview with.
3
4
  * ability to change access token param name.
4
5
  * bug: if mp label do not have text and was set as hidden, it should unhide after setting text.
@@ -7,6 +8,8 @@
7
8
  * bug: dealloc of Prime::Section will not be called for cell created in collection_data using #map.
8
9
  * bug: images does not render after reload table if using draw_with_layer (prerender not enabled).
9
10
  * bug: incorrect height (cropped) for draw label with lineSpacing in cases when there is just one line.
11
+ * use one style to set rounded corners for view/draw elements (remove :rounded_corners option)
12
+ * add :sides option to BaseElement border (like in draw)
10
13
  * add dsl for push notifications.
11
14
  * add some extensions/middleware system, at least for networking.
12
15
  * create "display_network_error" extension.
@@ -1,7 +1,7 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
3
  gem 'motion-cocoapods', '~> 1.4.1'
4
- gem 'motion-prime', '1.0.3'
4
+ gem 'motion-prime', '1.0.4'
5
5
 
6
6
  # add reside menu for sidebar support
7
7
  # gem 'prime_reside_menu', '~> 0.1.4'
@@ -18,7 +18,7 @@ Motion::Project::App.setup do |app|
18
18
  app.pods do
19
19
  pod 'NanoStore', '~> 2.7.7'
20
20
  pod 'SDWebImage'
21
- pod 'SVPullToRefresh', git: 'git@github.com:droidlabs/SVPullToRefresh.git'
21
+ pod 'SVPullToRefresh', git: 'https://github.com/droidlabs/SVPullToRefresh.git'
22
22
  pod 'MBAlertView'
23
23
  pod 'MBProgressHUD', '~> 0.8'
24
24
  end
@@ -43,13 +43,12 @@ class ApiClient
43
43
  end
44
44
 
45
45
  def page_url(path)
46
- "#{config.base}#{path}"
46
+ path_with_base(path, config.base)
47
47
  end
48
48
 
49
49
  def resource_url(path)
50
- # return if path.blank?
51
50
  base = config.resource_base? ? config.resource_base : config.base
52
- "#{base}#{path}"
51
+ path_with_base(path, base)
53
52
  end
54
53
 
55
54
  def request(method, path, params = {}, options = {}, &block)
@@ -73,7 +72,7 @@ class ApiClient
73
72
 
74
73
  def request!(method, path, data, files = nil, options = {}, &block)
75
74
  use_callback = block_given?
76
- path = "#{config.api_namespace}#{path}" unless path.starts_with?('http')
75
+ path = path_with_base(path, config.api_namespace)
77
76
  client_method = files.present? ? :"multipart_#{method}" : method
78
77
  AFMotion::Client.shared.send client_method, path, data do |response, form_data, progress|
79
78
  if form_data && files.present?
@@ -131,7 +130,6 @@ class ApiClient
131
130
 
132
131
  # TODO: temporary solution, add real caching system here
133
132
  def read_cache(key)
134
- puts "read cache #{key}"
135
133
  @cache ||= {}
136
134
  @cache[key]
137
135
  end
@@ -143,6 +141,10 @@ class ApiClient
143
141
  end
144
142
 
145
143
  protected
144
+ def path_with_base(path, base)
145
+ path.to_s.starts_with?('http') ? path : "#{base}#{path}"
146
+ end
147
+
146
148
  def allow_queue?(method, path, options)
147
149
  options[:allow_queue] && config.allow_queue?
148
150
  end
@@ -35,15 +35,22 @@ module MotionPrime
35
35
  @content_width = width_for_attributed_text(current_attributed_text)
36
36
  end
37
37
 
38
+ def multiline_content_width
39
+ unless computed_options[:width]
40
+ Prime.logger.error "Please set element width for multiline content width calculation (`#{self.name}` in section `#{section.try(:name)}`)"
41
+ end
42
+ width_for_attributed_text(current_attributed_text, computed_options[:width] - content_padding_width)
43
+ end
44
+
38
45
  def width_for_text(text)
39
46
  width_for_attributed_text(attributed_text_for_text(text))
40
47
  end
41
48
 
42
- def width_for_attributed_text(attributed_text)
49
+ def width_for_attributed_text(attributed_text, width = Float::MAX)
43
50
  min, max = computed_options[:min_width].to_f, computed_options[:max_width]
44
51
  return min if attributed_text.to_s.blank?
45
52
 
46
- rect = get_content_rect(attributed_text, Float::MAX)
53
+ rect = get_content_rect(attributed_text, width)
47
54
  [[rect.size.width.ceil, max].compact.min, min].max.ceil
48
55
  end
49
56
 
@@ -61,6 +68,9 @@ module MotionPrime
61
68
 
62
69
  def height_for_attributed_text(attributed_text)
63
70
  min, max = computed_options[:min_height].to_f, computed_options[:max_height]
71
+ unless computed_options[:width]
72
+ Prime.logger.error "Please set element width for content height calculation (`#{self.name}` in section `#{section.try(:name)}`)"
73
+ end
64
74
  return min if attributed_text.to_s.blank?
65
75
  rect = get_content_rect(attributed_text, computed_options[:width] - content_padding_width)
66
76
  [[rect.size.height.ceil, max].compact.min, min].max.ceil
@@ -92,7 +102,7 @@ module MotionPrime
92
102
  end
93
103
 
94
104
  def button_content_font
95
- computed_options[:title_label].try(:[], :font)
105
+ extract_font_from(computed_options[:title_label])
96
106
  end
97
107
 
98
108
  def input_content_text
@@ -101,7 +111,7 @@ module MotionPrime
101
111
 
102
112
  # TODO: normalize_object will not be required after refactoring computed options.
103
113
  def input_content_font
104
- font = input_value_text.blank? ? computed_options[:placeholder_font] : computed_options[:font]
114
+ font = input_value_text.blank? ? extract_font_from(computed_options, 'placeholder') : extract_font_from(computed_options)
105
115
  normalize_object(font, section || self)
106
116
  end
107
117
 
@@ -71,8 +71,12 @@ module MotionPrime
71
71
  end
72
72
  attributes[NSParagraphStyleAttributeName] = paragrah_style
73
73
  end
74
- attributes[NSForegroundColorAttributeName] = options[:text_color].uicolor if options[:text_color]
75
- attributes[NSFontAttributeName] = options[:font].uifont if options[:font]
74
+ if color = options[:text_color] || options[:title_color]
75
+ attributes[NSForegroundColorAttributeName] = color.uicolor
76
+ end
77
+ if font = extract_font_from(options)
78
+ attributes[NSFontAttributeName] = font.uifont
79
+ end
76
80
  [attributes, paragrah_style]
77
81
  end
78
82
  end
@@ -1,6 +1,7 @@
1
1
  motion_require '../helpers/has_normalizer'
2
2
  motion_require '../helpers/has_style_chain_builder'
3
3
  motion_require '../helpers/has_class_factory'
4
+ motion_require '../helpers/has_style_options'
4
5
  module MotionPrime
5
6
  class BaseElement
6
7
  # MotionPrime::BaseElement is container for UIView class elements with options.
@@ -10,6 +11,7 @@ module MotionPrime
10
11
  include HasNormalizer
11
12
  include HasStyleChainBuilder
12
13
  include HasClassFactory
14
+ include HasStyleOptions
13
15
  extend HasClassFactory
14
16
 
15
17
  attr_accessor :options, :section, :name,
@@ -54,6 +56,14 @@ module MotionPrime
54
56
  self.view.addTarget(target || section, action: action, forControlEvents: event.uicontrolevent)
55
57
  end
56
58
 
59
+ def notify_section_before_render
60
+ section.try(:before_element_render, self)
61
+ end
62
+
63
+ def notify_section_after_render
64
+ section.try(:after_element_render, self)
65
+ end
66
+
57
67
  def render(options = {}, &block)
58
68
  run_callbacks :render do
59
69
  render!(options, &block)
@@ -82,10 +92,10 @@ module MotionPrime
82
92
  block_options = compute_block_options || {}
83
93
  raw_options = self.options.except(:screen, :name, :block, :view_class).merge(block_options)
84
94
  compute_style_options(raw_options)
85
- raw_options = Styles.for(styles).merge(raw_options)
95
+ raw_options = Styles.for(styles).deep_merge(raw_options)
86
96
  @computed_options = raw_options
87
97
  normalize_options(@computed_options, section.try(:elements_eval_object), %w[
88
- font text placeholder title_label
98
+ font font_name font_size text placeholder title_label
89
99
  padding padding_left padding_right padding_top padding_bottom
90
100
  left right min_width min_outer_width max_width max_outer_width width
91
101
  top bottom min_height min_outer_height max_height max_outer_height height])
@@ -104,18 +114,27 @@ module MotionPrime
104
114
  if (changed_options & [:text, :size_to_fit]).any? && respond_to?(:size_to_fit)
105
115
  size_to_fit
106
116
  end
107
- section.try(:on_element_render, self)
108
117
  end
109
118
 
110
119
  def update_with_options(new_options = {})
111
- options.merge!(new_options)
120
+ options.deep_merge!(new_options)
112
121
  reload!
122
+ computed_options.deep_merge!(new_options)
113
123
  rerender!(new_options.keys)
114
124
  end
115
125
 
116
126
  def update_options(new_options)
117
- options.merge!(new_options)
127
+ options.deep_merge!(new_options)
118
128
  return unless view
129
+
130
+ required_options = if new_options.slice(:width, :height, :top, :left, :right, :bottom).any?
131
+ new_options[:calculate_frame] = true
132
+ [:width, :height, :top, :left, :right, :bottom]
133
+ elsif new_options.slice(:text, :title).any?
134
+ [:line_spacing, :line_height, :underline, :fragment_color, :text_alignment, :font, :font_name, :font_size, :line_break_mode, :number_of_lines]
135
+ end
136
+ new_options = computed_options.slice(*Array.wrap(required_options)).merge(new_options)
137
+
119
138
  ViewStyler.new(view, view.superview.try(:bounds), new_options).apply
120
139
  end
121
140
 
@@ -161,11 +180,10 @@ module MotionPrime
161
180
  end
162
181
 
163
182
  def compute_style_options(*style_sources)
164
- has_errors = section.respond_to?(:observing_errors?) && observing_errors? && has_errors?
165
-
166
183
  @styles = []
167
184
  if cell_section?
168
- @styles += compute_cell_style_options(style_sources, has_errors)
185
+ suffixes = section.style_suffixes if section.respond_to?(:style_suffixes)
186
+ @styles += compute_cell_style_options(style_sources, Array.wrap(suffixes))
169
187
  end
170
188
 
171
189
  mixins = []
@@ -189,11 +207,11 @@ module MotionPrime
189
207
 
190
208
  # custom style (from options or block options), using for TableViews as well
191
209
  @styles += custom_styles
192
- # pp @view_class.to_s + @styles.inspect; puts()
210
+ # pp(@view_class.to_s + @styles.inspect); puts()
193
211
  @styles
194
212
  end
195
213
 
196
- def compute_cell_style_options(style_sources, has_errors)
214
+ def compute_cell_style_options(style_sources, additional_suffixes)
197
215
  base_styles = {common: [], specific: []}
198
216
  suffixes = {common: [], specific: []}
199
217
  all_styles = []
@@ -208,13 +226,17 @@ module MotionPrime
208
226
  # form element: _input
209
227
  # table element: _image
210
228
  suffixes[:common] << @view_name.to_sym
211
- suffixes[:common] << :"#{@view_name}_with_errors" if has_errors
229
+ additional_suffixes.each do |additional_suffix|
230
+ suffixes[:common] << [@view_name, additional_suffix].join('_').to_sym
231
+ end
212
232
  end
213
233
  if name && name.to_s != @view_name
214
234
  # form element: _input
215
235
  # table element: _icon
216
236
  suffixes[:specific] << name.to_sym
217
- suffixes[:specific] << :"#{name}_with_errors" if has_errors
237
+ additional_suffixes.each do |additional_suffix|
238
+ suffixes[:specific] << [name, additional_suffix].join('_').to_sym
239
+ end
218
240
  end
219
241
  # form cell: base_form_field, base_form_string_field
220
242
  # form element: base_form_field_string_field, base_form_string_field_text_field, base_form_string_field_input
@@ -259,5 +281,8 @@ module MotionPrime
259
281
  set_callback :render, :after, method_name
260
282
  end
261
283
  end
284
+
285
+ before_render :notify_section_before_render
286
+ after_render :notify_section_after_render
262
287
  end
263
288
  end
@@ -22,7 +22,7 @@ module MotionPrime
22
22
  end
23
23
 
24
24
  def font
25
- computed_options[:title_label].try(:[], :font) || :system.uifont
25
+ extract_font_from(computed_options[:title_label]) || :system.uifont
26
26
  end
27
27
  end
28
28
  end
@@ -17,12 +17,18 @@ module MotionPrime
17
17
  corner_radius: options[:layer].try(:[], :corner_radius).to_f,
18
18
  border_width: options[:layer].try(:[], :border_width).to_f,
19
19
  border_color: options[:layer].try(:[], :border_color).try(:uicolor) || background_color,
20
+ border_sides: options[:layer].try(:[], :border_sides),
20
21
  dashes: options[:layer].try(:[], :dashes),
21
22
  }
22
23
  end
23
24
 
24
25
  def render!; end
25
26
 
27
+ def on_container_render
28
+ @view = nil
29
+ @computed_frame = nil
30
+ end
31
+
26
32
  def view
27
33
  @view ||= section.container_view
28
34
  end
@@ -3,7 +3,7 @@ module MotionPrime
3
3
  def draw_background_in_context(context = nil)
4
4
  context ||= UIGraphicsGetCurrentContext()
5
5
  options = draw_options
6
- rect, background_color, border_width, border_color, corner_radius, dashes_array = options.slice(:rect, :background_color, :border_width, :border_color, :corner_radius, :dashes).values
6
+ rect, background_color, border_width, border_color, border_sides, corner_radius, dashes_array = options.slice(:rect, :background_color, :border_width, :border_color, :border_sides, :corner_radius, :dashes).values
7
7
 
8
8
  return unless background_color || border_width > 0
9
9
 
@@ -34,7 +34,38 @@ module MotionPrime
34
34
  CGContextSetLineDash(context, dashes_array.count, dashes, 0) if dashes
35
35
  CGContextSetLineWidth(context, border_width)
36
36
  CGContextSetStrokeColorWithColor(context, border_color.uicolor.cgcolor)
37
- CGContextStrokeRect(context, rect)
37
+ if border_sides.present?
38
+ points = [
39
+ [rect.origin.x, rect.origin.y],
40
+ [rect.origin.x + rect.size.width, rect.origin.y],
41
+ [rect.origin.x + rect.size.width, rect.origin.y + rect.size.height],
42
+ [rect.origin.x, rect.origin.y + rect.size.height]
43
+ ]
44
+ CGContextMoveToPoint(context, *points[0])
45
+ if border_sides.include?(:top)
46
+ CGContextAddLineToPoint(context, *points[1])
47
+ else
48
+ CGContextMoveToPoint(context, *points[1])
49
+ end
50
+ if border_sides.include?(:right)
51
+ CGContextAddLineToPoint(context, *points[2])
52
+ else
53
+ CGContextMoveToPoint(context, *points[2])
54
+ end
55
+ if border_sides.include?(:bottom)
56
+ CGContextAddLineToPoint(context, *points[3])
57
+ else
58
+ CGContextMoveToPoint(context, *points[3])
59
+ end
60
+ if border_sides.include?(:left)
61
+ CGContextAddLineToPoint(context, *points[0])
62
+ else
63
+ CGContextMoveToPoint(context, *points[0])
64
+ end
65
+ CGContextStrokePath(context)
66
+ else
67
+ CGContextStrokeRect(context, rect)
68
+ end
38
69
  end
39
70
  CGContextSetFillColorWithColor(context, background_color.uicolor.cgcolor) if background_color
40
71
  CGContextFillRect(context, rect) if background_color
@@ -9,7 +9,10 @@ module MotionPrime
9
9
  image ||= computed_options[:default] if computed_options[:url]
10
10
 
11
11
  # already initialized image or image from resources or default image
12
- super.merge({image: image.try(:uiimage)})
12
+ super.merge({
13
+ image: image.try(:uiimage),
14
+ inner_rect: CGRectMake(frame_inner_left, frame_inner_top, frame_width, frame_height)
15
+ })
13
16
  end
14
17
 
15
18
  def draw_in(rect)
@@ -32,7 +35,7 @@ module MotionPrime
32
35
 
33
36
  border_width = options[:border_width]
34
37
  inset = border_width > 0 ? (border_width - 1 ).abs*0.5 : 0
35
- rect = CGRectInset(options[:rect], inset, inset)
38
+ rect = CGRectInset(options[:inner_rect], inset, inset)
36
39
  radius = options[:corner_radius].to_f if options[:corner_radius] && options[:masks_to_bounds]
37
40
 
38
41
  UIGraphicsPushContext(context)
@@ -52,9 +55,9 @@ module MotionPrime
52
55
 
53
56
  def draw_with_layer
54
57
  options = draw_options
55
- @layer.removeFromSuperlayer if @layer
58
+ @layer.try(:removeFromSuperlayer)
56
59
  return unless image = options[:image]
57
- rect = options[:rect]
60
+ rect = options[:inner_rect]
58
61
  radius = options[:corner_radius].to_f if options[:corner_radius] && options[:masks_to_bounds]
59
62
 
60
63
  @layer = CALayer.layer
@@ -106,8 +109,9 @@ module MotionPrime
106
109
  end
107
110
 
108
111
  def update_with_options(new_options = {})
112
+ self.image_data = nil if new_options.slice(:url, :image).any? || new_options.blank?
113
+ @layer.try(:removeFromSuperlayer)
109
114
  super
110
- self.image_data = nil if new_options.slice(:url, :image).any?
111
115
  end
112
116
  end
113
117
  end
@@ -9,7 +9,7 @@ module MotionPrime
9
9
  options = computed_options
10
10
  text = (options[:html] || options[:text]).to_s.gsub(/\A[\n\r]+/, '')
11
11
  text_color = (options[:text_color] || :black).uicolor
12
- font = (options[:font] || :system).uifont
12
+ font = (extract_font_from(options) || :system).uifont
13
13
 
14
14
  text_alignment_name = options.fetch(:text_alignment, :left)
15
15
  text_alignment = text_alignment_name.nstextalignment
@@ -31,7 +31,7 @@ module MotionPrime
31
31
  end
32
32
 
33
33
  def set_text(value)
34
- computed_options[:text] = value
34
+ options[:text] = computed_options[:text] = value
35
35
  styler = ViewStyler.new(view, CGRectZero, computed_options)
36
36
  if styler.options[:attributed_text]
37
37
  view.attributedText = styler.options[:attributed_text]