motion-prime 0.9.9 → 0.9.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +8 -2
  3. data/Gemfile.lock +2 -2
  4. data/ROADMAP.md +1 -3
  5. data/files/Gemfile +1 -1
  6. data/generators/templates/scaffold/table.rb +1 -1
  7. data/generators/templates/table.rb +1 -1
  8. data/motion-prime/config/base.rb +2 -2
  9. data/motion-prime/elements/_content_text_mixin.rb +1 -1
  10. data/motion-prime/elements/base_element.rb +14 -7
  11. data/motion-prime/elements/collection_view_cell.rb +7 -0
  12. data/motion-prime/elements/draw/image.rb +7 -2
  13. data/motion-prime/elements/table_view_cell.rb +1 -1
  14. data/motion-prime/helpers/has_normalizer.rb +1 -1
  15. data/motion-prime/helpers/has_search_bar.rb +1 -1
  16. data/motion-prime/models/_nano_bag_mixin.rb +1 -1
  17. data/motion-prime/models/model.rb +8 -8
  18. data/motion-prime/models/store.rb +1 -1
  19. data/motion-prime/screens/screen.rb +3 -3
  20. data/motion-prime/sections/_async_form_mixin.rb +2 -2
  21. data/motion-prime/sections/_async_table_mixin.rb +7 -7
  22. data/motion-prime/sections/_cell_section_mixin.rb +16 -11
  23. data/motion-prime/sections/_draw_section_mixin.rb +1 -0
  24. data/motion-prime/sections/{__section_with_container_mixin.rb → _section_with_container_mixin.rb} +2 -2
  25. data/motion-prime/sections/abstract_collection.rb +291 -0
  26. data/motion-prime/sections/base_section.rb +2 -2
  27. data/motion-prime/sections/collection/collection_delegate.rb +62 -0
  28. data/motion-prime/sections/form.rb +22 -18
  29. data/motion-prime/sections/form/base_field_section.rb +7 -7
  30. data/motion-prime/sections/form/form_delegate.rb +1 -1
  31. data/motion-prime/sections/form/form_header_section.rb +1 -1
  32. data/motion-prime/sections/form/password_field_section.rb +1 -1
  33. data/motion-prime/sections/form/static_field_section.rb +1 -1
  34. data/motion-prime/sections/form/string_field_section.rb +1 -1
  35. data/motion-prime/sections/form/text_field_section.rb +1 -1
  36. data/motion-prime/sections/grid.rb +92 -0
  37. data/motion-prime/sections/table.rb +26 -260
  38. data/motion-prime/sections/table/refresh_mixin.rb +3 -3
  39. data/motion-prime/sections/table/table_delegate.rb +1 -0
  40. data/motion-prime/styles/_mixins.rb +1 -1
  41. data/motion-prime/styles/base.rb +20 -6
  42. data/motion-prime/styles/form.rb +1 -1
  43. data/motion-prime/support/_control_content_alignment.rb +39 -0
  44. data/motion-prime/support/mp_button.rb +5 -13
  45. data/motion-prime/support/mp_collection_cell_with_section.rb +12 -0
  46. data/motion-prime/support/{mp_cell_content_view.rb → mp_table_cell_content_view.rb} +0 -0
  47. data/motion-prime/support/{mp_cell_with_section.rb → mp_table_cell_with_section.rb} +1 -1
  48. data/motion-prime/support/mp_text_field.rb +24 -18
  49. data/motion-prime/support/mp_text_view.rb +1 -0
  50. data/motion-prime/version.rb +1 -1
  51. data/motion-prime/views/_frame_calculator_mixin.rb +15 -11
  52. data/motion-prime/views/layout.rb +6 -4
  53. data/motion-prime/views/view_builder.rb +10 -0
  54. data/motion-prime/views/view_styler.rb +5 -1
  55. data/spec/factories/scaffold/sections/tasks/index_table.rb +1 -1
  56. data/spec/unit/support/filter_mixin_spec.rb +7 -3
  57. data/spec/unit/support/frame_calculator_mixin_spec.rb +43 -0
  58. metadata +13 -5
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ODMzMDQ2MmI4YTBmYTY4NWZiOTQzZjQ5NGVmMGEyNTFiN2NiZDhhOQ==
4
+ YzRmOTFjOTY1ODY2OTFlZTUwZDNlMDE1MWEwZDliYWVkMjBjM2VhNA==
5
5
  data.tar.gz: !binary |-
6
- MDRmZmM2Y2QwY2Q5ZDI0MzY4OTkyZjg4MTQ1YTQ3NDFkMjA0YmM5ZA==
6
+ YTY0M2Q1ZjAzMDI0MmY3ODE2ZGRkNmZmYTliNDY2NTQ4NjhjYjM3ZA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- ZDJlMGEwMzAxNjE5ZTVlMzIxYTJiMWI5ODg4N2JhYjIwMjQzMDg2NGVjYjA0
10
- YWVkMmZhNDA5MjgwMjZhMGU3YzNhM2UyNjBkZTJjZWJmZDRjNDU2NjdjOWNm
11
- ZTEwYzUwMGRjMjlmYTc5OGEzOTlkMmEwODQ0NzRmM2Q4ZWNiMzY=
9
+ NTgxZWNhZjE5ZDQwMDgwM2MxOWUzNWU2NzEyOTE5Nzk3MjI1YzcxMmEyYWFj
10
+ YmJjZjBkNGYxMWUyY2FiNDAyMGM1YzEwYjE5OGQwYjc2ZmQ0NWMyYzdmODAx
11
+ MWFmNTRkMDI1Yzc0NTRmMGJkN2IzZWM4ZDRhZGFkN2U1NDFhNWQ=
12
12
  data.tar.gz: !binary |-
13
- MGYxMmZiZGU1YzM2NWIzOTI2OGI0Zjc5MjlhYzQ2ZDU5YjM2ZWJhYTI1MjBj
14
- YTE5Nzc4MzdhN2JjYThjN2VmYTc5YjdiMWQ3MDY2YzM5ZmVmNmYwM2QyM2Zl
15
- MWNmMzY1MGU4MzA3NGRjOTdiNGMxYWNmNWNlZGE4ZjdhZDRjMmY=
13
+ ZTdmNjgyMzdhMjY1MDc2ZThlMTkwYjk4YjgxOTgzNTljYTZiZGI5ZTUyMTIy
14
+ ZDZkOTM3Y2EzM2E4NWVlZjQ2ZWI4OTU4MmFkYjMyYWIwMzEzN2ZlZGFhZjU4
15
+ ZDU4NmJhMWEwOWNhMTE5NTcxYTQ4N2Q4OTcwYjgyN2Y1OTcxNDQ=
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
+ === 0.9.9.1
2
+ * BREAKING CHANGE: width/height value have more priority than right/bottom
3
+ * BREAKING CHANGE: all methods starting with "table" in table section renamed to start with "collection"
4
+ * bug: content_vertical_alignment conflicts with padding.
5
+ * bug: content_vertical_alignment has not ideal centering.
6
+
1
7
  === 0.9.9
2
- * BREAKING CHANGE: table delegate methods in table section does not accept table_view as first param.
8
+ * BREAKING CHANGE: table delegate methods in table section does not accept collection_view as first param.
3
9
  See https://github.com/droidlabs/motion-prime/commit/c8f7b2e4fd1665a45309585484ac211381854f62
4
10
  * Bug fixes
5
11
 
@@ -11,7 +17,7 @@
11
17
  * BREAKING CHANGE: screen#set_options renamed to screen#set_options_for.
12
18
  * BREAKING CHANGE: section#reload_section renamed to section#hard_reload_section. in common cases use section#reload.
13
19
  * BREAKING CHANGE: form#reload_cell_section renamed to form#hard_reload_cell_section. in common cases use form#reload_cell_sections.
14
- * BREAKING CHANGE: table#reset_data renamed to table#reset_table_data
20
+ * BREAKING CHANGE: table#reset_data renamed to table#reset_collection_data
15
21
 
16
22
  === 0.9.6
17
23
  * BREAKING CHANGE: proc for form field option will be executed in context of form, not field.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- motion-prime (0.9.9)
4
+ motion-prime (0.9.9.1)
5
5
  activesupport
6
6
  afmotion (~> 2.1.0)
7
7
  bubble-wrap (~> 1.6.0)
@@ -65,7 +65,7 @@ GEM
65
65
  open4 (1.3.3)
66
66
  rake (10.3.1)
67
67
  rm-digest (0.0.2)
68
- sugarcube (1.6.0)
68
+ sugarcube (1.6.1)
69
69
  thor (0.19.1)
70
70
  xcodeproj (0.16.1)
71
71
  activesupport (~> 3.0)
data/ROADMAP.md CHANGED
@@ -1,10 +1,8 @@
1
1
  === 1.0.0
2
- * bug: content_vertical_alignment conflicts with padding.
3
- * bug: content_vertical_alignment has not ideal centering.
4
2
  * bug: if mp label do not have text and was set as hidden, it should unhide after setting text.
5
3
  * bug: size_to_fit works incorrect with relative width.
6
4
  * bug: bind_keyboard_close breaks bind_guesture
7
- * bug: dealloc of Prime::Section will not be called for cell created in table_data using #map.
5
+ * bug: dealloc of Prime::Section will not be called for cell created in collection_data using #map.
8
6
  * bug: images does not render after reload table if using draw_with_layer (prerender not enabled).
9
7
  * add dsl for push notifications
10
8
  * add some extensions/middleware system, at least for networking.
data/files/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
3
  gem 'motion-cocoapods', '~> 1.4.1'
4
- gem 'motion-prime', '0.9.8'
4
+ gem 'motion-prime', '0.9.9.1'
5
5
 
6
6
  # add reside menu for sidebar support
7
7
  # gem 'prime_reside_menu', '~> 0.1.4'
@@ -1,5 +1,5 @@
1
1
  class <%= @p_class_name %>IndexTableSection < Prime::TableSection
2
- def table_data
2
+ def collection_data
3
3
  <%= @s_class_name %>.all.map do |model|
4
4
  <%= @p_class_name %>IndexCellSection.new(model: model)
5
5
  end
@@ -1,5 +1,5 @@
1
1
  class <%= @table_class_name %> < Prime::TableSection
2
- def table_data
2
+ def collection_data
3
3
  # This method should return Array of sections, e.g:
4
4
  <%= @model_class_name %>.map do |model|
5
5
  <%= @cell_class_name %>.new(model: model)
@@ -1,4 +1,4 @@
1
- motion_require './config.rb'
1
+ motion_require './config'
2
2
  MotionPrime::Config.configure do |config|
3
3
  # MODELS
4
4
  if MotionPrime.env.test?
@@ -32,7 +32,7 @@ MotionPrime::Config.configure do |config|
32
32
  colors.dark = 0x333333
33
33
  colors.error = 0xef471f
34
34
  end
35
-
35
+
36
36
  # SECTIONS
37
37
  config.prime.cell_section.mixins = [Prime::CellSectionMixin]
38
38
 
@@ -1,4 +1,4 @@
1
- motion_require './_text_mixin.rb'
1
+ motion_require './_text_mixin'
2
2
  module MotionPrime
3
3
  module ElementContentTextMixin
4
4
  include ElementTextMixin
@@ -85,7 +85,7 @@ module MotionPrime
85
85
  raw_options = Styles.for(styles).merge(raw_options)
86
86
  @computed_options = raw_options
87
87
  normalize_options(@computed_options, section.try(:elements_eval_object), %w[
88
- text placeholder font title_label
88
+ font text placeholder title_label
89
89
  padding padding_left padding_right padding_top padding_bottom
90
90
  left right min_width min_outer_width max_width max_outer_width width
91
91
  top bottom min_height min_outer_height max_height max_outer_height height])
@@ -134,6 +134,14 @@ module MotionPrime
134
134
  view.setUserInteractionEnabled true
135
135
  end
136
136
 
137
+ def cell_section?
138
+ section.respond_to?(:cell_section_name)
139
+ end
140
+
141
+ def cell_element?
142
+ @view_class == 'UICollectionViewCell' || @view_class == 'UITableViewCell'
143
+ end
144
+
137
145
  protected
138
146
  def reset_computed_values
139
147
  @content_height = nil
@@ -150,10 +158,9 @@ module MotionPrime
150
158
 
151
159
  def compute_style_options(*style_sources)
152
160
  has_errors = section.respond_to?(:observing_errors?) && observing_errors? && has_errors?
153
- is_cell_section = section.respond_to?(:cell_section_name)
154
161
 
155
162
  @styles = []
156
- if is_cell_section
163
+ if cell_section?
157
164
  @styles += compute_cell_style_options(style_sources, has_errors)
158
165
  end
159
166
 
@@ -178,7 +185,7 @@ module MotionPrime
178
185
 
179
186
  # custom style (from options or block options), using for TableViews as well
180
187
  @styles += custom_styles
181
- # puts @view_class.to_s + @styles.inspect, ''
188
+ # pp @view_class.to_s + @styles.inspect; puts()
182
189
  @styles
183
190
  end
184
191
 
@@ -193,7 +200,7 @@ module MotionPrime
193
200
  if section.section_styles
194
201
  section.section_styles.each { |type, values| base_styles[type] += values }
195
202
  end
196
- if @view_name != 'base' && @view_name != 'table_view_cell'
203
+ if @view_name != 'base' && !cell_element?
197
204
  # form element: _input
198
205
  # table element: _image
199
206
  suffixes[:common] << @view_name.to_sym
@@ -213,7 +220,7 @@ module MotionPrime
213
220
  build_styles_chain(base_styles[:common], suffixes.values.flatten)
214
221
  elsif suffixes[:specific].any?
215
222
  build_styles_chain(base_styles[:common], suffixes[:specific])
216
- elsif @view_name == 'table_view_cell'
223
+ elsif cell_element?
217
224
  base_styles[:common]
218
225
  end
219
226
  all_styles += Array.wrap(common_styles)
@@ -223,7 +230,7 @@ module MotionPrime
223
230
  # table element: categories_table_cell_image, categories_table_title_image
224
231
  specific_base_common_suffix_styles = if suffixes[:common].any?
225
232
  build_styles_chain(base_styles[:specific], suffixes[:common])
226
- elsif suffixes[:specific].empty? && @view_name == 'table_view_cell'
233
+ elsif suffixes[:specific].empty? && cell_element?
227
234
  base_styles[:specific]
228
235
  end
229
236
  all_styles += Array.wrap(specific_base_common_suffix_styles)
@@ -0,0 +1,7 @@
1
+ module MotionPrime
2
+ class TableViewCellElement < BaseElement
3
+ def view_class
4
+ "MPCollectionCellWithSection"
5
+ end
6
+ end
7
+ end
@@ -15,7 +15,12 @@ module MotionPrime
15
15
  def draw_in(rect)
16
16
  return if computed_options[:hidden]
17
17
  draw_background_in_context(UIGraphicsGetCurrentContext())
18
- computed_options[:draw_in_rect] ? draw_in_context(UIGraphicsGetCurrentContext()) : draw_with_layer
18
+ # bug - when it's a CollectionView we get invalid frame when drawing in a layer
19
+ if computed_options[:draw_in_rect] || view.is_a?(MPCollectionCellWithSection)
20
+ draw_in_context(UIGraphicsGetCurrentContext())
21
+ else
22
+ draw_with_layer
23
+ end
19
24
  load_image
20
25
  end
21
26
 
@@ -64,7 +69,7 @@ module MotionPrime
64
69
  end
65
70
 
66
71
  def strong_references
67
- [section, (section.table if section.respond_to?(:cell_section_name))].compact
72
+ [section, (section.collection_section if section.respond_to?(:cell_section_name))].compact
68
73
  end
69
74
 
70
75
  def load_image
@@ -1,7 +1,7 @@
1
1
  module MotionPrime
2
2
  class TableViewCellElement < BaseElement
3
3
  def view_class
4
- "MPCellWithSection"
4
+ "MPTableCellWithSection"
5
5
  end
6
6
  end
7
7
  end
@@ -48,7 +48,7 @@ module MotionPrime
48
48
  if element?
49
49
  [self.class.name, self.name, section.try(:name)]
50
50
  elsif self.is_a?(Section)
51
- [self.class.name, self.name, @table.try(:class).try(:name)]
51
+ [self.class.name, self.name, @collection_section.try(:class).try(:name)]
52
52
  else
53
53
  [self.class.name]
54
54
  end
@@ -11,7 +11,7 @@ module MotionPrime
11
11
  if target
12
12
  target.addSubview @_search_bar
13
13
  elsif is_a?(TableSection)
14
- self.table_view.tableHeaderView = @_search_bar
14
+ self.collection_view.tableHeaderView = @_search_bar
15
15
  end
16
16
 
17
17
  @search_callback = block
@@ -1,4 +1,4 @@
1
- motion_require './_finder_mixin.rb'
1
+ motion_require './_finder_mixin'
2
2
  module MotionPrime
3
3
  module NanoBagMixin
4
4
  include FilterMixin
@@ -1,12 +1,12 @@
1
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'
2
+ motion_require './_nano_bag_mixin'
3
+ motion_require './_finder_mixin'
4
+ motion_require './_base_mixin'
5
+ motion_require './_sync_mixin'
6
+ motion_require './_association_mixin'
7
+ motion_require './_dirty_mixin'
8
+ motion_require './store'
9
+ motion_require './store_extension'
10
10
  module MotionPrime
11
11
  class Model < NSFNanoObject
12
12
  include MotionPrime::HasAuthorization
@@ -1,4 +1,4 @@
1
- motion_require '../config/base.rb'
1
+ motion_require '../config/base'
2
2
  module MotionPrime
3
3
  class Store
4
4
  def self.create(type = nil, path = nil)
@@ -1,6 +1,6 @@
1
- motion_require '../support/mp_view_controller.rb'
2
- motion_require '../views/layout.rb'
3
- motion_require '../screens/_base_mixin.rb'
1
+ motion_require '../support/mp_view_controller'
2
+ motion_require '../views/layout'
3
+ motion_require '../screens/_base_mixin'
4
4
  motion_require './extensions/_indicators_mixin'
5
5
  motion_require './extensions/_navigation_bar_mixin'
6
6
  motion_require '../helpers/has_authorization'
@@ -1,13 +1,13 @@
1
1
  module Prime
2
2
  module AsyncFormMixin
3
- def reload_table_data
3
+ def reload_collection_data
4
4
  # FIXME: duplicated cells (see cached_cell error)
5
5
  return super unless async_data?
6
6
  sections = NSMutableIndexSet.new
7
7
  number_of_groups.times do |section_id|
8
8
  sections.addIndex(section_id)
9
9
  end
10
- table_view.reloadSections sections, withRowAnimation: UITableViewRowAnimationFade
10
+ collection_view.reloadSections sections, withRowAnimation: UITableViewRowAnimationFade
11
11
  end
12
12
  end
13
13
  end
@@ -24,9 +24,9 @@ module Prime
24
24
  # Reset async loaded table data and preloader queue.
25
25
  #
26
26
  # @return [Boolean] true
27
- def reset_table_data
28
- super # must be before to update fixed_table_data
29
- @async_loaded_data = async_data? ? fixed_table_data : nil
27
+ def reset_collection_data
28
+ super # must be before to update fixed_collection_data
29
+ @async_loaded_data = async_data? ? fixed_collection_data : nil
30
30
  Array.wrap(@preloader_queue).each { |queue| queue[:state] = :cancelled }
31
31
  @preloader_next_starts_from = nil
32
32
  end
@@ -151,9 +151,9 @@ module Prime
151
151
  end
152
152
 
153
153
  private
154
- def set_table_data
154
+ def set_collection_data
155
155
  sections = load_sections_async
156
- prepare_table_cell_sections(sections)
156
+ prepare_collection_cell_sections(sections)
157
157
  @data = sections
158
158
  reset_data_stamps
159
159
  @data
@@ -163,9 +163,9 @@ module Prime
163
163
  @async_loaded_data || begin
164
164
  ref_key = allocate_strong_references
165
165
  BW::Reactor.schedule_on_main do
166
- @async_loaded_data = fixed_table_data
166
+ @async_loaded_data = fixed_collection_data
167
167
  @data = nil
168
- reload_table_data
168
+ reload_collection_data
169
169
  on_async_data_loaded
170
170
  release_strong_references(ref_key)
171
171
  end
@@ -1,11 +1,11 @@
1
- # This Mixin will be included only to sections, which added as cell to table section.
1
+ # This Mixin will be included only to sections, which added as cell to collection section.
2
2
  module MotionPrime
3
3
  module CellSectionMixin
4
4
  extend ::MotionSupport::Concern
5
5
 
6
6
  # include SectionWithContainerMixin # already included in draw_section_mixin
7
7
 
8
- attr_writer :table
8
+ attr_writer :collection_section
9
9
  attr_reader :pending_display
10
10
 
11
11
  included do
@@ -13,12 +13,17 @@ module MotionPrime
13
13
  container_element type: :table_view_cell
14
14
  end
15
15
 
16
+ def collection_section
17
+ @collection_section ||= options[:collection_section].try(:weak_ref)
18
+ end
19
+
16
20
  def table
17
- @table ||= options[:table].try(:weak_ref)
21
+ Prime.logger.info "Section#table is deprecated: #{caller[0]}"
22
+ collection_section
18
23
  end
19
24
 
20
25
  def section_styles
21
- @section_styles ||= table.try(:cell_section_styles, self) || {}
26
+ @section_styles ||= collection_section.try(:cell_section_styles, self) || {}
22
27
  end
23
28
 
24
29
  def cell_type
@@ -29,31 +34,31 @@ module MotionPrime
29
34
 
30
35
  def cell_section_name
31
36
  self.class.custom_cell_section_name || begin
32
- return name unless table
33
- table_name = table.name.gsub('_table', '')
37
+ return name unless collection_section
38
+ table_name = collection_section.name.gsub('_table', '')
34
39
  name.gsub("#{table_name}_", '')
35
40
  end
36
41
  end
37
42
 
38
43
  def container_bounds
39
- @container_bounds ||= CGRectMake(0, 0, table.table_view.bounds.size.width, container_height)
44
+ @container_bounds ||= CGRectMake(0, 0, collection_section.collection_view.bounds.size.width, container_height)
40
45
  end
41
46
 
42
- # should do nothing, because table section will care about it.
47
+ # should do nothing, because collection section will care about it.
43
48
  def render_container(options = {}, &block)
44
49
  block.call
45
50
  end
46
51
 
47
52
  def init_container_element(options = {})
48
53
  options[:styles] ||= []
49
- options[:styles] = [:"#{table.name}_first_cell"] if table.data.first == self
50
- options[:styles] = [:"#{table.name}_last_cell"] if table.data.last == self
54
+ options[:styles] = [:"#{collection_section.name}_first_cell"] if collection_section.data.first == self
55
+ options[:styles] = [:"#{collection_section.name}_last_cell"] if collection_section.data.last == self
51
56
  super(options)
52
57
  end
53
58
 
54
59
  def pending_display!
55
60
  @pending_display = true
56
- display unless table.decelerating
61
+ display unless collection_section.decelerating
57
62
  end
58
63
 
59
64
  def display
@@ -1,3 +1,4 @@
1
+ motion_require '_section_with_container_mixin'
1
2
  module MotionPrime
2
3
  module DrawSectionMixin
3
4
  extend ::MotionSupport::Concern
@@ -18,8 +18,8 @@ module MotionPrime
18
18
  has_drawn_content: true
19
19
  })
20
20
  container_element_options = self.class.container_element_options.clone
21
- type = container_element_options.delete(:type)
22
- options.merge!(container_element_options)
21
+ options = (container_element_options || {}).merge(options)
22
+ type = options.delete(:type)
23
23
  MotionPrime::BaseElement.factory(type, options)
24
24
  end
25
25
  end