motion-prime 0.8.1 → 0.8.2
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.
- checksums.yaml +8 -8
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/ROADMAP.md +3 -0
- data/files/Gemfile +1 -1
- data/motion-prime/api_client.rb +5 -2
- data/motion-prime/core_ext/kernel.rb +36 -0
- data/motion-prime/elements/_content_text_mixin.rb +32 -11
- data/motion-prime/elements/base_element.rb +33 -16
- data/motion-prime/elements/draw.rb +10 -4
- data/motion-prime/elements/draw/image.rb +26 -15
- data/motion-prime/elements/map.rb +5 -0
- data/motion-prime/models/_association_mixin.rb +0 -3
- data/motion-prime/models/_base_mixin.rb +24 -3
- data/motion-prime/models/_filter_mixin.rb +28 -0
- data/motion-prime/models/_sync_mixin.rb +13 -10
- data/motion-prime/models/association_collection.rb +41 -16
- data/motion-prime/models/errors.rb +46 -24
- data/motion-prime/models/model.rb +8 -0
- data/motion-prime/screens/_sections_mixin.rb +1 -1
- data/motion-prime/screens/extensions/_indicators_mixin.rb +4 -2
- data/motion-prime/screens/extensions/_navigation_bar_mixin.rb +1 -1
- data/motion-prime/screens/screen.rb +4 -0
- data/motion-prime/sections/_async_form_mixin.rb +12 -0
- data/motion-prime/sections/_async_table_mixin.rb +193 -0
- data/motion-prime/sections/_cell_section_mixin.rb +6 -6
- data/motion-prime/sections/_draw_section_mixin.rb +13 -5
- data/motion-prime/sections/base_section.rb +62 -36
- data/motion-prime/sections/form.rb +19 -35
- data/motion-prime/sections/form/base_field_section.rb +42 -34
- data/motion-prime/sections/form/static_field_section.rb +9 -0
- data/motion-prime/sections/table.rb +143 -201
- data/motion-prime/sections/table/table_delegate.rb +15 -15
- data/motion-prime/services/table_data_indexes.rb +12 -2
- data/motion-prime/styles/base.rb +1 -1
- data/motion-prime/styles/form.rb +6 -6
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/layout.rb +5 -2
- data/motion-prime/views/view_styler.rb +2 -0
- data/spec/models/association_collection_spec.rb +28 -6
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzY4ZDViYzJiOGMwNWM5YTdhN2UwZjNlYTNlOWQ0OTc0MDM4NDM4Yw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ODRiYzRiZDAxNTMzYzdiNzVmNTg3N2FhNjY0M2E1ZGQ2NDU5YjdlZQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MDAyNTU2NzE0ODhhZWIxNzg5M2Y3ZWRlOWVlYWE0MjJmMDEzM2ZlMzE2NDI1
|
10
|
+
ZmMyODZjZGEyYjBmYmJlODZhZWRmYzZmZjg3OWE5ZmMzMDkxMjBkMGE2YjY1
|
11
|
+
NDNiMjMzN2I1NWRhNjVjNjJkYTc3NmZhYTI0ZmRlYTcxYjA4ZWM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MWJiZDQ3OGJlN2QzNWRlNjVhNTg2MGQyN2U2NThlNTUwNmUyMmFhMGZiN2Y1
|
14
|
+
MmQ2YzY0MjFmYzA4YjU4NzVkOThkY2Q4ZmNiM2Q4YTFiMjBlMWE1OGI2MWFm
|
15
|
+
NmZjOGQ2YWU5NGQ4NDJjM2Y2ZTc2MGUxN2IxMzExNGQ0YzViZTU=
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
=== 0.8.2
|
2
|
+
* bug fixes.
|
3
|
+
* added #clone method for Model.
|
4
|
+
* added #filter method for association collection.
|
5
|
+
* memory leak fixes.
|
6
|
+
|
1
7
|
=== 0.8.1
|
2
8
|
* renamed submit element in submit field to button element.
|
3
9
|
* renamed date_picker element in date_picker field to input element.
|
data/Gemfile.lock
CHANGED
data/ROADMAP.md
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
=== 0.8.2
|
2
2
|
* Move api_client and model sync mixin to prime_api gem.
|
3
|
+
* Move bind keyboard events to forms.
|
3
4
|
|
4
5
|
=== 0.9.0
|
5
6
|
* bug: if mp label do not have text and was set as hidden, it should unhide after setting text
|
6
7
|
* bug: size_to_fit works incorrect with relative width.
|
7
8
|
* bug: bind_keyboard_close breaks bind_guesture
|
9
|
+
* bug: dealloc of Prime::Section will not be called for cell created in table_data using #map.
|
10
|
+
* bug: images does not render after reload table if using draw_with_layer (prerender not enabled).
|
8
11
|
* add clone to models to prevent problems when bag_key is overrided
|
9
12
|
* add dsl for push notifications
|
10
13
|
* add some extensions/middleware system, at least for networking.
|
data/files/Gemfile
CHANGED
data/motion-prime/api_client.rb
CHANGED
@@ -17,7 +17,7 @@ class ApiClient
|
|
17
17
|
end
|
18
18
|
if config.sign_request?
|
19
19
|
signature = RmDigest::MD5.hexdigest(
|
20
|
-
config.signature_secret + params.keys.map(&:to_s).sort.join
|
20
|
+
config.signature_secret + filter_sign_params(params).keys.map(&:to_s).sort.join
|
21
21
|
)
|
22
22
|
params.merge!(sign: signature)
|
23
23
|
end
|
@@ -37,7 +37,7 @@ class ApiClient
|
|
37
37
|
auth_data = response.object
|
38
38
|
|
39
39
|
self.access_token = auth_data[:access_token] if auth_data
|
40
|
-
block.call(auth_data, response.operation.response.statusCode) if use_callback
|
40
|
+
block.call(auth_data, response.operation.response.try(:statusCode)) if use_callback
|
41
41
|
end
|
42
42
|
true
|
43
43
|
end
|
@@ -111,6 +111,9 @@ class ApiClient
|
|
111
111
|
end
|
112
112
|
|
113
113
|
private
|
114
|
+
def filter_sign_params(params)
|
115
|
+
params.except(:_files)
|
116
|
+
end
|
114
117
|
|
115
118
|
def config
|
116
119
|
MotionPrime::Config.api_client
|
@@ -15,6 +15,42 @@ class Kernel
|
|
15
15
|
self
|
16
16
|
end
|
17
17
|
|
18
|
+
def allocate_strong_references(key = nil)
|
19
|
+
unless self.respond_to?(:strong_references)
|
20
|
+
Prime.logger.debug "User must define `strong_references` in `#{self.class.name}`"
|
21
|
+
return false
|
22
|
+
end
|
23
|
+
|
24
|
+
refs = Array.wrap(self.strong_references).compact
|
25
|
+
unless refs.present?
|
26
|
+
Prime.logger.debug "`strong_references` are empty for `#{self.class.name}`"
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
|
30
|
+
@_strong_references ||= {}
|
31
|
+
key ||= [@_strong_references.count, Time.now.to_i].join('_')
|
32
|
+
@_strong_references[key] = refs.map(&:strong_ref)
|
33
|
+
key
|
34
|
+
end
|
35
|
+
|
36
|
+
def release_strong_references(key = nil)
|
37
|
+
unless self.respond_to?(:strong_references)
|
38
|
+
Prime.logger.debug "User must define `strong_references` in `#{self.class.name}`"
|
39
|
+
return false
|
40
|
+
end
|
41
|
+
key ||= @_strong_references.keys.last
|
42
|
+
@_strong_references.delete(key)
|
43
|
+
key
|
44
|
+
end
|
45
|
+
|
46
|
+
def allocated_references_released?
|
47
|
+
unless self.respond_to?(:strong_references)
|
48
|
+
Prime.logger.debug "User must define `strong_references` in `#{self.class.name}`"
|
49
|
+
return false
|
50
|
+
end
|
51
|
+
@_strong_references.all? { |key, ref| @_strong_references.count; ref.retainCount == @_strong_references.count }
|
52
|
+
end
|
53
|
+
|
18
54
|
def clear_instance_variables(options = {})
|
19
55
|
ivars = self.instance_variables
|
20
56
|
excluded_ivars = Array.wrap(options[:except]).map(&:to_s)
|
@@ -11,15 +11,19 @@ module MotionPrime
|
|
11
11
|
(is_a?(ButtonElement) ? button_content_font : input_content_font) || :system.uifont
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def current_attributed_text
|
15
15
|
if view.try(:is_a?, UITextView) && view.text.present?
|
16
16
|
text = view.attributedText
|
17
17
|
text += ' ' if text.to_s.end_with?("\n") # does not respect \n at the end by default
|
18
|
-
|
18
|
+
text
|
19
|
+
else
|
20
|
+
attributed_text_for_text(content_text)
|
19
21
|
end
|
22
|
+
end
|
20
23
|
|
24
|
+
def attributed_text_for_text(text)
|
21
25
|
options = {
|
22
|
-
text:
|
26
|
+
text: text,
|
23
27
|
font: content_font,
|
24
28
|
line_spacing: computed_options[:line_spacing],
|
25
29
|
line_height: computed_options[:line_height]
|
@@ -28,11 +32,19 @@ module MotionPrime
|
|
28
32
|
end
|
29
33
|
|
30
34
|
def content_width
|
35
|
+
@content_width = width_for_attributed_text(current_attributed_text)
|
36
|
+
end
|
37
|
+
|
38
|
+
def width_for_text(text)
|
39
|
+
width_for_attributed_text(attributed_text_for_text(text))
|
40
|
+
end
|
41
|
+
|
42
|
+
def width_for_attributed_text(attributed_text)
|
31
43
|
min, max = computed_options[:min_width].to_f, computed_options[:max_width]
|
32
|
-
return min if
|
44
|
+
return min if attributed_text.blank?
|
33
45
|
|
34
|
-
rect = get_content_rect(Float::MAX)
|
35
|
-
|
46
|
+
rect = get_content_rect(attributed_text, Float::MAX)
|
47
|
+
[[rect.size.width.ceil, max].compact.min, min].max.ceil
|
36
48
|
end
|
37
49
|
|
38
50
|
def cached_content_width
|
@@ -40,10 +52,19 @@ module MotionPrime
|
|
40
52
|
end
|
41
53
|
|
42
54
|
def content_height
|
55
|
+
@content_height = height_for_attributed_text(current_attributed_text)
|
56
|
+
end
|
57
|
+
|
58
|
+
def height_for_text(text)
|
59
|
+
height_for_attributed_text(attributed_text_for_text(text))
|
60
|
+
end
|
61
|
+
|
62
|
+
def height_for_attributed_text(attributed_text)
|
43
63
|
min, max = computed_options[:min_height].to_f, computed_options[:max_height]
|
44
|
-
return min if
|
45
|
-
|
46
|
-
|
64
|
+
return min if attributed_text.blank?
|
65
|
+
|
66
|
+
rect = get_content_rect(attributed_text, computed_options[:width] - content_padding_width)
|
67
|
+
[[rect.size.height.ceil, max].compact.min, min].max.ceil
|
47
68
|
end
|
48
69
|
|
49
70
|
def cached_content_height
|
@@ -55,14 +76,14 @@ module MotionPrime
|
|
55
76
|
end
|
56
77
|
|
57
78
|
private
|
58
|
-
def get_content_rect(width)
|
79
|
+
def get_content_rect(text, width)
|
59
80
|
raise "Please set element width for content size calculation" unless width
|
60
81
|
|
61
82
|
options = NSStringDrawingUsesLineFragmentOrigin
|
62
83
|
if is_a?(TextViewElement)
|
63
84
|
options |= NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine
|
64
85
|
end
|
65
|
-
|
86
|
+
text.boundingRectWithSize([width, Float::MAX], options: options, context:nil)
|
66
87
|
end
|
67
88
|
|
68
89
|
def button_content_text
|
@@ -27,9 +27,19 @@ module MotionPrime
|
|
27
27
|
@name = options[:name]
|
28
28
|
@block = options[:block]
|
29
29
|
@view_name = self.class_name_without_kvo.demodulize.underscore.gsub(/(_draw)?_element/, '')
|
30
|
+
|
31
|
+
if Prime.env.development?
|
32
|
+
@_element_info = "#{@name} #{view_name} #{section.try(:name)} #{screen.class}"
|
33
|
+
@@_allocated_elements ||= []
|
34
|
+
@@_allocated_elements << @_element_info
|
35
|
+
end
|
30
36
|
end
|
31
37
|
|
32
38
|
def dealloc
|
39
|
+
if Prime.env.development?
|
40
|
+
index = @@_allocated_elements.index(@_element_info)
|
41
|
+
@@_allocated_elements.delete_at(index) if index
|
42
|
+
end
|
33
43
|
Prime.logger.dealloc_message :element, self, self.name
|
34
44
|
super
|
35
45
|
end
|
@@ -41,12 +51,12 @@ module MotionPrime
|
|
41
51
|
|
42
52
|
def render(options = {}, &block)
|
43
53
|
run_callbacks :render do
|
44
|
-
render!(&block)
|
54
|
+
render!(options, &block)
|
45
55
|
end
|
46
56
|
end
|
47
57
|
|
48
|
-
def render!(&block)
|
49
|
-
view = screen.add_view class_factory(view_class), computed_options do |view|
|
58
|
+
def render!(options = {}, &block)
|
59
|
+
view = screen.add_view class_factory(view_class), computed_options.merge(options) do |view|
|
50
60
|
@view = view
|
51
61
|
block.try(:call, view, self)
|
52
62
|
end
|
@@ -72,11 +82,14 @@ module MotionPrime
|
|
72
82
|
normalize_options(@computed_options, section, %w[text placeholder font title_label padding padding_left padding_right min_width min_outer_width max_width max_outer_width width left right])
|
73
83
|
end
|
74
84
|
|
85
|
+
def reload!
|
86
|
+
compute_options!
|
87
|
+
end
|
88
|
+
|
75
89
|
def update_with_options(new_options = {})
|
76
90
|
options.merge!(new_options)
|
77
|
-
|
91
|
+
reload!
|
78
92
|
view.try(:removeFromSuperview)
|
79
|
-
@view = nil
|
80
93
|
render
|
81
94
|
end
|
82
95
|
|
@@ -107,29 +120,33 @@ module MotionPrime
|
|
107
120
|
|
108
121
|
def compute_style_options(*style_sources)
|
109
122
|
has_errors = section.respond_to?(:observing_errors?) && observing_errors? && has_errors?
|
110
|
-
is_cell_section = section.respond_to?(:
|
123
|
+
is_cell_section = section.respond_to?(:cell_section_name)
|
111
124
|
|
112
125
|
@styles = []
|
113
126
|
if is_cell_section
|
114
127
|
@styles += compute_cell_style_options(style_sources, has_errors)
|
115
128
|
end
|
116
129
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
130
|
+
mixins = []
|
131
|
+
custom_styles = []
|
132
|
+
style_sources.each do |source|
|
133
|
+
if source_mixins = source.delete(:mixins)
|
134
|
+
mixins += Array.wrap(normalize_object(source_mixins, section))
|
135
|
+
end
|
136
|
+
if source_styles = source.delete(:styles)
|
137
|
+
custom_styles += Array.wrap(normalize_object(source_styles, section))
|
138
|
+
end
|
139
|
+
end
|
140
|
+
# styles got from mixins option
|
141
|
+
@styles += mixins.map{ |m| :"_mixin_#{m}" }
|
122
142
|
|
123
143
|
# don't use present? here, it's slower, while this method should be very fast
|
124
144
|
if section && section.name && section.name != '' && name && name != ''
|
125
145
|
# using for base sections
|
126
146
|
@styles << [section.name, name].join('_').to_sym
|
127
147
|
end
|
128
|
-
# custom style (from options or block options), using for TableViews as well
|
129
|
-
custom_styles = style_sources.map do |source|
|
130
|
-
normalize_object(source.delete(:styles), section)
|
131
|
-
end.flatten
|
132
148
|
|
149
|
+
# custom style (from options or block options), using for TableViews as well
|
133
150
|
@styles += custom_styles
|
134
151
|
# puts @view_class.to_s + @styles.inspect, ''
|
135
152
|
@styles
|
@@ -140,7 +157,7 @@ module MotionPrime
|
|
140
157
|
suffixes = {common: [], specific: []}
|
141
158
|
all_styles = []
|
142
159
|
|
143
|
-
# following example in Prime::TableSection#
|
160
|
+
# following example in Prime::TableSection#cell_section_styles
|
144
161
|
# form element/cell: <base|user>_form_field, <base|user>_form_string_field, user_form_field_email
|
145
162
|
# table element/cell: <base|categories>_table_cell, categories_table_title
|
146
163
|
if section.section_styles
|
@@ -60,8 +60,9 @@ module MotionPrime
|
|
60
60
|
def computed_right; computed_left + computed_width end
|
61
61
|
def computed_inner_right; computed_right - content_padding_right end
|
62
62
|
|
63
|
-
def bind_gesture(action, receiver = nil)
|
64
|
-
|
63
|
+
def bind_gesture(action, receiver = nil, target = nil)
|
64
|
+
target ||= section
|
65
|
+
target.bind_gesture_on_container_for(self, action, receiver)
|
65
66
|
end
|
66
67
|
|
67
68
|
def hide
|
@@ -78,10 +79,15 @@ module MotionPrime
|
|
78
79
|
view.setNeedsDisplay
|
79
80
|
end
|
80
81
|
|
81
|
-
def
|
82
|
-
|
82
|
+
def reload!
|
83
|
+
reset_computed_values
|
83
84
|
compute_options!
|
84
85
|
section.cached_draw_image = nil
|
86
|
+
end
|
87
|
+
|
88
|
+
def update_with_options(new_options = {})
|
89
|
+
options.merge!(new_options)
|
90
|
+
reload!
|
85
91
|
view.setNeedsDisplay
|
86
92
|
end
|
87
93
|
|
@@ -14,7 +14,6 @@ module MotionPrime
|
|
14
14
|
|
15
15
|
def draw_in(rect)
|
16
16
|
return if computed_options[:hidden]
|
17
|
-
|
18
17
|
draw_background_in_context(UIGraphicsGetCurrentContext())
|
19
18
|
computed_options[:draw_in_rect] ? draw_in_context(UIGraphicsGetCurrentContext()) : draw_with_layer
|
20
19
|
load_image
|
@@ -49,48 +48,60 @@ module MotionPrime
|
|
49
48
|
|
50
49
|
def draw_with_layer
|
51
50
|
options = draw_options
|
51
|
+
@layer.removeFromSuperlayer if @layer
|
52
52
|
return unless image = options[:image]
|
53
53
|
rect = options[:rect]
|
54
54
|
radius = options[:corner_radius].to_f if options[:corner_radius] && options[:masks_to_bounds]
|
55
55
|
|
56
|
-
layer = CALayer.layer
|
57
|
-
layer.contents = image.CGImage
|
58
|
-
layer.frame = rect
|
59
|
-
layer.bounds = rect
|
56
|
+
@layer = CALayer.layer
|
57
|
+
@layer.contents = image.CGImage
|
58
|
+
@layer.frame = rect
|
59
|
+
@layer.bounds = rect
|
60
60
|
|
61
|
-
layer.masksToBounds = options[:masks_to_bounds]
|
62
|
-
layer.cornerRadius = radius if radius
|
61
|
+
@layer.masksToBounds = options[:masks_to_bounds]
|
62
|
+
@layer.cornerRadius = radius if radius
|
63
|
+
view.layer.addSublayer(@layer)
|
64
|
+
end
|
63
65
|
|
64
|
-
|
66
|
+
def strong_references
|
67
|
+
[section, (section.table if section.respond_to?(:cell_section_name))].compact
|
65
68
|
end
|
66
69
|
|
67
70
|
def load_image
|
68
|
-
return if image_data || !computed_options[:url]
|
69
|
-
|
70
|
-
|
71
|
+
return if @loading || image_data || !computed_options[:url]
|
72
|
+
@loading = true
|
73
|
+
|
74
|
+
ref_key = allocate_strong_references
|
71
75
|
BW::Reactor.schedule do
|
72
76
|
manager = SDWebImageManager.sharedManager
|
73
77
|
manager.downloadWithURL(computed_options[:url],
|
74
78
|
options: 0,
|
75
79
|
progress: lambda{ |r_size, e_size| },
|
76
80
|
completed: lambda{ |image, error, type, finished|
|
77
|
-
if !image ||
|
78
|
-
@
|
81
|
+
if !image || allocated_references_released?
|
82
|
+
@loading = false
|
83
|
+
release_strong_references(ref_key)
|
79
84
|
return
|
80
85
|
end
|
81
86
|
|
82
87
|
self.image_data = image
|
83
88
|
|
84
89
|
section.cached_draw_image = nil
|
85
|
-
if section.respond_to?(:
|
90
|
+
if section.respond_to?(:cell_section_name)
|
86
91
|
section.pending_display!
|
87
92
|
else
|
88
93
|
self.view.performSelectorOnMainThread :setNeedsDisplay, withObject: nil, waitUntilDone: false
|
89
94
|
end
|
90
|
-
@
|
95
|
+
@loading = false
|
96
|
+
release_strong_references(ref_key)
|
91
97
|
}
|
92
98
|
)
|
93
99
|
end
|
94
100
|
end
|
101
|
+
|
102
|
+
def update_with_options(new_options = {})
|
103
|
+
super
|
104
|
+
self.image_data = nil if new_options.has_key?(:url)
|
105
|
+
end
|
95
106
|
end
|
96
107
|
end
|