motion-prime 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
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