motion-prime 0.9.6 → 0.9.7

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 (90) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile.lock +6 -6
  4. data/README.md +1 -10
  5. data/Rakefile +0 -1
  6. data/app/app_delegate.rb +1 -1
  7. data/bin/prime +1 -1
  8. data/files/Gemfile +1 -1
  9. data/motion-prime/api_client.rb +87 -31
  10. data/motion-prime/config/base.rb +20 -11
  11. data/motion-prime/config/config.rb +9 -3
  12. data/motion-prime/core_ext/kernel.rb +2 -1
  13. data/motion-prime/core_ext/nil_class.rb +5 -0
  14. data/motion-prime/delegate/app_delegate.rb +5 -0
  15. data/motion-prime/elements/base_element.rb +21 -2
  16. data/motion-prime/elements/draw.rb +6 -16
  17. data/motion-prime/helpers/has_authorization.rb +1 -1
  18. data/motion-prime/models/_base_mixin.rb +1 -1
  19. data/motion-prime/prime.rb +4 -0
  20. data/motion-prime/screens/extensions/_indicators_mixin.rb +16 -10
  21. data/motion-prime/screens/screen.rb +1 -1
  22. data/motion-prime/sections/_async_table_mixin.rb +1 -2
  23. data/motion-prime/sections/_draw_section_mixin.rb +3 -1
  24. data/motion-prime/sections/base_section.rb +37 -26
  25. data/motion-prime/sections/form.rb +23 -8
  26. data/motion-prime/sections/form/base_field_section.rb +1 -15
  27. data/motion-prime/sections/form/date_field_section.rb +1 -1
  28. data/motion-prime/sections/form/password_field_section.rb +1 -1
  29. data/motion-prime/sections/form/select_field_section.rb +1 -1
  30. data/motion-prime/sections/form/string_field_section.rb +1 -1
  31. data/motion-prime/sections/form/submit_field_section.rb +1 -1
  32. data/motion-prime/sections/form/text_field_section.rb +1 -1
  33. data/motion-prime/sections/table.rb +58 -27
  34. data/motion-prime/sections/table/refresh_mixin.rb +1 -1
  35. data/motion-prime/services/logger.rb +60 -21
  36. data/motion-prime/support/consts.rb +11 -0
  37. data/motion-prime/version.rb +1 -1
  38. data/motion-prime/views/layout.rb +5 -4
  39. data/motion-prime/views/view_styler.rb +3 -0
  40. data/spec/{helpers → factories}/delegates.rb +0 -3
  41. data/spec/{helpers → factories}/init.rb +0 -0
  42. data/spec/{helpers → factories}/models.rb +0 -0
  43. data/spec/factories/scaffold/models/task.rb +4 -0
  44. data/spec/factories/scaffold/screens/tasks.rb +45 -0
  45. data/spec/factories/scaffold/sections/tasks/form.rb +31 -0
  46. data/spec/factories/scaffold/sections/tasks/index_cell.rb +4 -0
  47. data/spec/factories/scaffold/sections/tasks/index_table.rb +12 -0
  48. data/spec/factories/scaffold/sections/tasks/show.rb +3 -0
  49. data/spec/factories/scaffold/styles/tasks.rb +18 -0
  50. data/spec/{helpers → factories}/screens.rb +0 -0
  51. data/spec/factories/sections.rb +9 -0
  52. data/spec/features/scaffold/index.rb +14 -0
  53. data/spec/features/screens/open_screen.rb +14 -2
  54. data/spec/helpers/has_content.rb +25 -0
  55. data/spec/unit/models/dirty_spec.rb +0 -1
  56. data/spec/unit/models/model_spec.rb +2 -0
  57. data/spec/unit/prime/logger.rb +49 -0
  58. data/spec/unit/sections/section_spec.rb +59 -0
  59. data/travis.sh +1 -1
  60. metadata +36 -41
  61. data/doc/FAQ.md +0 -2
  62. data/doc/SECTION.md +0 -7
  63. data/doc/STYLE.md +0 -39
  64. data/doc/code/getting_started.rb +0 -106
  65. data/doc/code/models.rb +0 -36
  66. data/doc/code/screens.rb +0 -93
  67. data/doc/code/sections.rb +0 -65
  68. data/doc/code/tables.rb +0 -54
  69. data/doc/docs/docco.css +0 -337
  70. data/doc/docs/getting_started.html +0 -195
  71. data/doc/docs/index.html +0 -205
  72. data/doc/docs/models.html +0 -115
  73. data/doc/docs/public/fonts/aller-bold.eot +0 -0
  74. data/doc/docs/public/fonts/aller-bold.ttf +0 -0
  75. data/doc/docs/public/fonts/aller-bold.woff +0 -0
  76. data/doc/docs/public/fonts/aller-light.eot +0 -0
  77. data/doc/docs/public/fonts/aller-light.ttf +0 -0
  78. data/doc/docs/public/fonts/aller-light.woff +0 -0
  79. data/doc/docs/public/fonts/fleurons.eot +0 -0
  80. data/doc/docs/public/fonts/fleurons.ttf +0 -0
  81. data/doc/docs/public/fonts/fleurons.woff +0 -0
  82. data/doc/docs/public/fonts/novecento-bold.eot +0 -0
  83. data/doc/docs/public/fonts/novecento-bold.ttf +0 -0
  84. data/doc/docs/public/fonts/novecento-bold.woff +0 -0
  85. data/doc/docs/public/images/gray.png +0 -0
  86. data/doc/docs/public/stylesheets/normalize.css +0 -375
  87. data/doc/docs/screens.html +0 -187
  88. data/doc/docs/sections.html +0 -138
  89. data/doc/docs/tables.html +0 -128
  90. data/spec/helpers/sections.rb +0 -3
@@ -11,7 +11,7 @@ module MotionPrime
11
11
  end
12
12
  element :error_message, type: :error_message, text: proc { |field| field.observing_errors? and field.all_errors.join("\n") }
13
13
 
14
- after_render :bind_select_button
14
+ after_element_render :button, :bind_select_button
15
15
 
16
16
  def bind_select_button
17
17
  view(:button).on :touch_down do
@@ -9,7 +9,7 @@ module MotionPrime
9
9
  end
10
10
 
11
11
  element :error_message, type: :error_message, text: proc { |field| field.all_errors.join("\n") if field.observing_errors? }
12
- after_render :bind_text_input
12
+ after_element_render :input, :bind_text_input
13
13
 
14
14
  def value
15
15
  view(:input).text
@@ -5,7 +5,7 @@ module MotionPrime
5
5
  end
6
6
  element :error_message, type: :error_message, text: proc { |field| field.all_errors.join("\n") if field.observing_errors? }
7
7
 
8
- after_render :bind_button
8
+ after_element_render :button, :bind_button
9
9
 
10
10
  def bind_button
11
11
  view(:button).on :touch do
@@ -8,7 +8,7 @@ module MotionPrime
8
8
  end
9
9
 
10
10
  element :error_message, type: :error_message, text: proc { |field| field.observing_errors? and field.all_errors.join("\n") }
11
- after_render :bind_text_input
11
+ after_element_render :input, :bind_text_input
12
12
 
13
13
  def value
14
14
  view(:input).text
@@ -14,7 +14,7 @@ module MotionPrime
14
14
  before_render :render_table
15
15
  after_render :init_pull_to_refresh
16
16
  delegate :init_pull_to_refresh, to: :table_delegate
17
-
17
+ delegate :set_options, :update_options, to: :table_element, allow_nil: true
18
18
 
19
19
  # Return sections which will be used to render as table cells.
20
20
  #
@@ -49,7 +49,7 @@ module MotionPrime
49
49
  #
50
50
  # @return [Boolean] true
51
51
  def reload_data
52
- reset_data
52
+ reset_table_data
53
53
  reload_table_data
54
54
  end
55
55
 
@@ -60,7 +60,7 @@ module MotionPrime
60
60
  reload_data
61
61
  end
62
62
 
63
- # Reload table view
63
+ # Reload table view data
64
64
  #
65
65
  # @return [Boolean] true
66
66
  def reload_table_data
@@ -78,7 +78,7 @@ module MotionPrime
78
78
  # Reset all table data.
79
79
  #
80
80
  # @return [Boolean] true
81
- def reset_data
81
+ def reset_table_data
82
82
  @did_appear = false
83
83
  @data = nil
84
84
  @data_stamp = nil
@@ -104,7 +104,7 @@ module MotionPrime
104
104
  #
105
105
  # @param cell sections [Prime::Section, Array<Prime::Section>] cells which will be removed from table view.
106
106
  # @return [Array<NSIndexPath>] index paths of removed cells.
107
- def delete_cell_sections(sections)
107
+ def delete_cell_sections(sections, &block)
108
108
  paths = []
109
109
  Array.wrap(sections).each do |section|
110
110
  index = index_for_cell_section(section)
@@ -113,13 +113,46 @@ module MotionPrime
113
113
  delete_from_data(index)
114
114
  end
115
115
  if paths.any?
116
- table_view.beginUpdates
117
- table_view.deleteRowsAtIndexPaths(paths, withRowAnimation: UITableViewRowAnimationLeft)
118
- table_view.endUpdates
116
+ UIView.animate(duration: 0, after: block) do
117
+ table_view.beginUpdates
118
+ table_view.deleteRowsAtIndexPaths(paths, withRowAnimation: UITableViewRowAnimationLeft)
119
+ table_view.endUpdates
120
+ end
119
121
  end
120
122
  paths
121
123
  end
122
124
 
125
+ # Reloads cells with animation, executes given block before reloading.
126
+ #
127
+ # @param cell sections [Prime::Section, Array<Prime::Section>] cells which will be updated.
128
+ # @param around callback [Proc] Callback which will be executed before reloading.
129
+ # @return [Array<NSIndexPath>] index paths of reloaded cells.
130
+ def reload_cell_sections(sections, &block)
131
+ paths = []
132
+ Array.wrap(sections).each_with_index do |section, counter|
133
+ index = index_for_cell_section(section)
134
+ next Prime.logger.debug("Reload section: `#{section.name}` is not in the list") unless index
135
+ paths << index
136
+ block.call(section, index, counter)
137
+ set_data_stamp(section.object_id)
138
+ section.reload
139
+ end
140
+ table_view.reloadRowsAtIndexPaths(paths, withRowAnimation: UITableViewRowAnimationFade)
141
+ paths
142
+ end
143
+
144
+ # Changes height of cells with animation.
145
+ #
146
+ # @param cell sections [Prime::Section, Array<Prime::Section>] cells which will be updated.
147
+ # @param height [Integer, Array<Integer>] new height of all cells, or height for each cell.
148
+ # @return [Array<NSIndexPath>] index paths of removed cells.
149
+ def resize_cell_sections(sections, height)
150
+ reload_cell_sections(sections) do |section, index, counter|
151
+ container_height = height.is_a?(Array) ? height[counter] : height
152
+ section.container_options[:height] = container_height
153
+ end
154
+ end
155
+
123
156
  # Delete section from data at index
124
157
  #
125
158
  # @param index [NSIndexPath] index of cell which will be removed from table data.
@@ -127,24 +160,18 @@ module MotionPrime
127
160
  if flat_data?
128
161
  delete_from_flat_data(index)
129
162
  else
130
- delete_from_groped_data(index)
163
+ delete_from_grouped_data(index)
131
164
  end
132
165
  end
133
166
 
134
- def delete_from_flat_data(index)
135
- @data[index.row] = nil
136
- @data.delete_at(index.row)
137
- end
138
-
139
- def delete_from_groped_data(index)
140
- @data[index.section][index.row] = nil
141
- @data[index.section].delete_at(index.row)
142
- end
143
-
167
+ # Get index path for cell section
168
+ #
169
+ # @param section [Prime::Section] cell section.
170
+ # @return index [NSIndexPath] index of cell section.
144
171
  def index_for_cell_section(section)
145
172
  if flat_data?
146
173
  row = @data.try(:index, section)
147
- NSIndexPath.indexPathForRow(row, inSection: 0)
174
+ NSIndexPath.indexPathForRow(row, inSection: 0) if row
148
175
  else
149
176
  (@data || []).each_with_index do |cell_sections, group|
150
177
  row = cell_sections.index(section)
@@ -153,12 +180,6 @@ module MotionPrime
153
180
  end
154
181
  end
155
182
 
156
- def reload_cell_section(section)
157
- section.elements.values.each(&:compute_options!)
158
- section.cached_draw_image = nil
159
- # TODO: reset date stamps, reload row
160
- end
161
-
162
183
  def table_styles
163
184
  type = self.is_a?(FormSection) ? :base_form : :base_table
164
185
 
@@ -326,7 +347,7 @@ module MotionPrime
326
347
  styles: styles,
327
348
  parent_view: table_view,
328
349
  reuse_identifier: reuse_identifier,
329
- section: header
350
+ section: header.weak_ref
330
351
  )
331
352
  wrapper.render do |container_view, container_element|
332
353
  header.container_element = container_element
@@ -355,6 +376,16 @@ module MotionPrime
355
376
  end
356
377
 
357
378
  private
379
+ def delete_from_flat_data(index)
380
+ @data[index.row] = nil
381
+ @data.delete_at(index.row)
382
+ end
383
+
384
+ def delete_from_grouped_data(index)
385
+ @data[index.section][index.row] = nil
386
+ @data[index.section].delete_at(index.row)
387
+ end
388
+
358
389
  def display_pending_cells
359
390
  table_view.visibleCells.each do |cell_view|
360
391
  if cell_view.section && cell_view.section.pending_display
@@ -4,7 +4,7 @@ module MotionPrime
4
4
  screen.automaticallyAdjustsScrollViewInsets = false
5
5
 
6
6
  table_view.addPullToRefreshWithActionHandler(block) # block must be a variable
7
- screen.set_options table_view.pullToRefreshView, styles: [:base_pull_to_refresh]
7
+ screen.set_options_for table_view.pullToRefreshView, styles: [:base_pull_to_refresh]
8
8
  end
9
9
 
10
10
  def finish_pull_to_refresh
@@ -5,50 +5,89 @@ module MotionPrime
5
5
  LOGGER_DEBUG_LEVEL = 2
6
6
  LOGGER_DEALLOC_LEVEL = 3
7
7
 
8
+ COLORS = {
9
+ red: [ "\e[0;31m", "\e[0m" ],
10
+ green: [ "\e[0;32m", "\e[0m" ],
11
+ yellow: [ "\e[0;33m", "\e[0m" ],
12
+ blue: [ "\e[0;34m", "\e[0m" ],
13
+ none: [ "", ""]
14
+ }
15
+
8
16
  class_attribute :level, :dealloc_items
17
+ attr_accessor :disabled
9
18
 
10
19
  def initialize
11
20
  @default_level = Config.logger.level.nil? ? :info : Config.logger.level
21
+ @disabled = false
22
+ end
23
+
24
+ # Log message, colorized if using simulator.
25
+ # @param message [Array<String>, String] Message or array of messages to log.
26
+ # @param color [Symbol] Color of message: red, green, yellow, blue.
27
+ # @return message [Array<String>, String] Logged message
28
+ def log(objects, label = '', color = :none)
29
+ message = "#{label || 'PRIME_LOG'} : " + Array.wrap(objects).map(&:inspect).join(',')
30
+ if Device.simulator?
31
+ color_parts = COLORS[color] || COLORS[:none]
32
+ output(color_parts.first + message + color_parts.last)
33
+ else
34
+ output(message)
35
+ end
36
+ objects
37
+ end
38
+
39
+ # Output message, using "puts" for simulator and NSLog for Device.
40
+ # @param message [String] Message or array of messages to output.
41
+ # @return message [Array<String>, String] Message
42
+ def output(message)
43
+ return if disabled
44
+ if Device.simulator?
45
+ puts(message)
46
+ else
47
+ NSLog(message)
48
+ end
49
+ message
12
50
  end
13
51
 
14
52
  def error(*args)
15
- pp("PRIME_ERROR", *args) if LOGGER_ERROR_LEVEL <= current_level
53
+ log(args, "PRIME_ERROR", :red) if LOGGER_ERROR_LEVEL <= current_level
16
54
  end
17
55
 
18
56
  def info(*args)
19
- pp("PRIME_INFO", *args) if LOGGER_INFO_LEVEL <= current_level
57
+ log(args, "PRIME_INFO", :green) if LOGGER_INFO_LEVEL <= current_level
20
58
  end
21
59
 
22
60
  def debug(*args)
23
- pp("PRIME_DEBUG", *args) if LOGGER_DEBUG_LEVEL <= current_level
61
+ log(args, "PRIME_DEBUG", :yellow) if LOGGER_DEBUG_LEVEL <= current_level
24
62
  end
25
63
 
26
64
  def dealloc_message(type, object, *args)
27
65
  if LOGGER_DEALLOC_LEVEL <= current_level
28
66
  if dealloc_items.include?(type.to_s)
29
- pp "Deallocating #{type}", object.object_id, object.to_s, *args
67
+ log([object.object_id, object.to_s] + args, "DEALLOC #{type}", :yellow)
30
68
  end
31
69
  end
32
70
  end
33
71
 
34
- def dealloc_items
35
- self.class.dealloc_items || []
36
- end
72
+ private
73
+ def dealloc_items
74
+ self.class.dealloc_items || []
75
+ end
37
76
 
38
- def current_level
39
- current_level = self.class.level || @default_level
40
- case current_level.to_s
41
- when 'error'
42
- LOGGER_ERROR_LEVEL
43
- when 'info'
44
- LOGGER_INFO_LEVEL
45
- when 'debug'
46
- LOGGER_DEBUG_LEVEL
47
- when 'dealloc'
48
- LOGGER_DEALLOC_LEVEL
49
- else
50
- 2
77
+ def current_level
78
+ current_level = self.class.level || @default_level
79
+ case current_level.to_s
80
+ when 'error'
81
+ LOGGER_ERROR_LEVEL
82
+ when 'info'
83
+ LOGGER_INFO_LEVEL
84
+ when 'debug'
85
+ LOGGER_DEBUG_LEVEL
86
+ when 'dealloc'
87
+ LOGGER_DEALLOC_LEVEL
88
+ else
89
+ 2
90
+ end
51
91
  end
52
- end
53
92
  end
54
93
  end
@@ -0,0 +1,11 @@
1
+ # this constants should be listed here to be accessible in constantize
2
+
3
+ UIControlContentHorizontalAlignmentCenter
4
+ UIControlContentHorizontalAlignmentLeft
5
+ UIControlContentHorizontalAlignmentRight
6
+ UIControlContentHorizontalAlignmentFill
7
+
8
+ UIControlContentVerticalAlignmentCenter
9
+ UIControlContentVerticalAlignmentTop
10
+ UIControlContentVerticalAlignmentBottom
11
+ UIControlContentVerticalAlignmentFill
@@ -1,3 +1,3 @@
1
1
  module MotionPrime
2
- VERSION = "0.9.6"
2
+ VERSION = "0.9.7"
3
3
  end
@@ -18,7 +18,7 @@ module MotionPrime
18
18
  view = builder.view
19
19
  insert_index = options.delete(:at_index)
20
20
 
21
- set_options(view, options, &block)
21
+ set_options_for(view, options, &block)
22
22
  if superview = render_target || view_stack.last
23
23
  insert_index ? superview.insertSubview(view, atIndex: insert_index) : superview.addSubview(view)
24
24
  end
@@ -26,16 +26,17 @@ module MotionPrime
26
26
  view
27
27
  end
28
28
 
29
- def set_options(view, options = {}, &block)
29
+ def set_options_for(view, options = {}, &block)
30
30
  ViewStyler.new(view, options.delete(:parent_bounds), options).apply
31
31
  view_stack.push(view)
32
32
  block.call(view) if block_given?
33
33
  view_stack.pop
34
34
  end
35
+ alias_method :update_options_for, :set_options_for
35
36
 
36
37
  def setup(view, options = {}, &block)
37
- puts "DEPRECATION: screen#setup is deprecated, please use screen#set_options instead"
38
- set_options(view, options, &block)
38
+ puts "DEPRECATION: screen#setup is deprecated, please use screen#set_options_for instead"
39
+ set_options_for(view, options, &block)
39
40
  end
40
41
 
41
42
  def view_stack
@@ -147,6 +147,9 @@ module MotionPrime
147
147
  if key == 'content_horizontal_alignment' && value.is_a?(Symbol) && %[left right center fill].include?(value.to_s)
148
148
  view.setValue "UIControlContentHorizontalAlignment#{value.camelize}".constantize, forKey: camelize_factory(key)
149
149
  true
150
+ elsif key == 'content_vertical_alignment' && value.is_a?(Symbol) && %[top bottom center fill].include?(value.to_s)
151
+ view.setValue "UIControlContentHorizontalAlignment#{value.camelize}".constantize, forKey: camelize_factory(key)
152
+ true
150
153
  elsif key.end_with?('alignment') && value.is_a?(Symbol)
151
154
  view.setValue value.uitextalignment, forKey: camelize_factory(key)
152
155
  true
@@ -1,6 +1,3 @@
1
- # motion_require '../../motion-prime/helpers/has_authorization'
2
- # motion_require './../motion-prime/delegate/_base_mixin'
3
- # motion_require './../motion-prime/delegate/_navigation_mixin'
4
1
  AppDelegate.send :include, MotionPrime::HasAuthorization
5
2
  AppDelegate.send :include, MotionPrime::DelegateBaseMixin
6
3
  AppDelegate.send :include, MotionPrime::DelegateNavigationMixin
File without changes
File without changes
@@ -0,0 +1,4 @@
1
+ class Task < Prime::Model
2
+ timestamp_attributes
3
+ attribute :title
4
+ end
@@ -0,0 +1,45 @@
1
+ class TasksScreen < Prime::Screen
2
+ title "Tasks"
3
+
4
+ # open_screen "tasks#index"
5
+ def index
6
+ set_title "Tasks"
7
+ set_navigation_right_button 'New' do
8
+ open_screen "tasks#new"
9
+ end
10
+ set_section :tasks_index_table
11
+ end
12
+
13
+ # open_screen "tasks#show"
14
+ def show
15
+ @model = params[:model]
16
+ set_title "Show Task"
17
+ set_navigation_back_button 'Back'
18
+ set_navigation_right_button 'Edit' do
19
+ open_screen "tasks#edit", params: { model: @model }
20
+ end
21
+ set_section :tasks_show, model: @model
22
+ end
23
+
24
+ # open_screen "tasks#edit"
25
+ def edit
26
+ @model = params[:model]
27
+ set_title "Edit Task"
28
+ set_navigation_back_button 'Cancel'
29
+ set_section :tasks_form, model: @model
30
+ end
31
+
32
+ # open_screen "tasks#new"
33
+ def new
34
+ @model = Task.new
35
+ set_title "New Task"
36
+ set_navigation_back_button 'Cancel'
37
+ set_section :tasks_form, model: @model
38
+ end
39
+
40
+ def on_return
41
+ if action?(:index) || action?(:show)
42
+ refresh
43
+ end
44
+ end
45
+ end