motion-prime 0.3.1 → 0.3.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 +7 -3
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/ROADMAP.md +12 -0
- data/motion-prime/api_client.rb +1 -0
- data/motion-prime/app_delegate.rb +1 -1
- data/motion-prime/elements/_content_padding_mixin.rb +49 -0
- data/motion-prime/elements/_field_dimensions_mixin.rb +37 -21
- data/motion-prime/elements/_text_dimensions_mixin.rb +0 -4
- data/motion-prime/elements/base.rb +20 -7
- data/motion-prime/elements/button.rb +2 -1
- data/motion-prime/elements/draw/label.rb +19 -8
- data/motion-prime/elements/error_message.rb +2 -1
- data/motion-prime/elements/image.rb +1 -0
- data/motion-prime/elements/label.rb +10 -10
- data/motion-prime/elements/text_field.rb +2 -0
- data/motion-prime/models/bag.rb +8 -3
- data/motion-prime/models/model.rb +1 -1
- data/motion-prime/models/sync.rb +17 -8
- data/motion-prime/screens/_aliases_mixin.rb +2 -0
- data/motion-prime/screens/_base_mixin.rb +19 -52
- data/motion-prime/screens/_navigation_mixin.rb +31 -29
- data/motion-prime/screens/base_screen.rb +8 -0
- data/motion-prime/screens/extensions/_indicators_mixin.rb +26 -0
- data/motion-prime/screens/{_navigation_bar_mixin.rb → extensions/_navigation_bar_mixin.rb} +0 -0
- data/motion-prime/screens/sidebar_container_screen.rb +1 -1
- data/motion-prime/sections/base.rb +1 -1
- data/motion-prime/sections/form.rb +5 -2
- data/motion-prime/sections/form/base_field_section.rb +2 -2
- data/motion-prime/support/_key_value_store.rb +1 -1
- data/motion-prime/support/_padding_attribute.rb +60 -0
- data/motion-prime/support/dm_button.rb +20 -20
- data/motion-prime/support/dm_text_field.rb +12 -17
- data/motion-prime/support/dm_text_view.rb +1 -1
- data/motion-prime/support/mp_label.rb +9 -0
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/layout.rb +1 -0
- data/motion-prime/views/styles.rb +1 -1
- data/motion-prime/views/view_styler.rb +5 -1
- data/spec/helpers/models.rb +8 -1
- data/travis.sh +1 -3
- metadata +8 -3
@@ -74,7 +74,7 @@ module MotionPrime
|
|
74
74
|
# User.new(name: "Bob", age: 10)
|
75
75
|
#
|
76
76
|
# @return MotionPrime::BaseModel unsaved model
|
77
|
-
def new(data = {})
|
77
|
+
def new(data = {}, options = {})
|
78
78
|
data.keys.each { |k|
|
79
79
|
unless self.attributes.member? k.to_sym
|
80
80
|
raise StoreError, "'#{k}' is not a defined attribute for this model"
|
data/motion-prime/models/sync.rb
CHANGED
@@ -116,6 +116,7 @@ module MotionPrime
|
|
116
116
|
self.send(:"#{key}=", value)
|
117
117
|
end
|
118
118
|
end
|
119
|
+
self
|
119
120
|
end
|
120
121
|
|
121
122
|
def fetch_associations(sync_options = {}, &block)
|
@@ -153,8 +154,8 @@ module MotionPrime
|
|
153
154
|
|
154
155
|
use_callback = block_given?
|
155
156
|
puts "SYNC: started sync for #{key} in #{self.class_name_without_kvo}"
|
156
|
-
api_client.get normalize_sync_url(options[:sync_url]) do |
|
157
|
-
data =
|
157
|
+
api_client.get normalize_sync_url(options[:sync_url]) do |response, status_code|
|
158
|
+
data = options.has_key?(:sync_key) ? response[options[:sync_key]] : response
|
158
159
|
if data
|
159
160
|
# Update/Create existing records
|
160
161
|
data.each do |attributes|
|
@@ -174,10 +175,10 @@ module MotionPrime
|
|
174
175
|
end
|
175
176
|
save if sync_options[:save]
|
176
177
|
puts "SYNC: finished sync for #{key} in #{self.class_name_without_kvo}"
|
177
|
-
block.call(data, status_code) if use_callback
|
178
|
+
block.call(data, status_code, response) if use_callback
|
178
179
|
else
|
179
180
|
puts "SYNC ERROR: failed sync for #{key} in #{self.class_name_without_kvo}"
|
180
|
-
block.call(data, status_code) if use_callback
|
181
|
+
block.call(data, status_code, response) if use_callback
|
181
182
|
end
|
182
183
|
end
|
183
184
|
end
|
@@ -185,8 +186,8 @@ module MotionPrime
|
|
185
186
|
def fetch_has_one(key, options = {}, &block)
|
186
187
|
use_callback = block_given?
|
187
188
|
puts "SYNC: started sync for #{key} in #{self.class_name_without_kvo}"
|
188
|
-
api_client.get normalize_sync_url(options[:sync_url]) do |
|
189
|
-
data =
|
189
|
+
api_client.get normalize_sync_url(options[:sync_url]) do |response, status_code|
|
190
|
+
data = options.has_key?(:sync_key) ? response[options[:sync_key]] : response
|
190
191
|
if data.present?
|
191
192
|
model = self.send(key)
|
192
193
|
unless model
|
@@ -195,10 +196,10 @@ module MotionPrime
|
|
195
196
|
end
|
196
197
|
model.fetch_with_attributes(data)
|
197
198
|
model.save if sync_options[:save]
|
198
|
-
block.call(data, status_code) if use_callback
|
199
|
+
block.call(data, status_code, response) if use_callback
|
199
200
|
else
|
200
201
|
puts "SYNC ERROR: failed sync for #{key} in #{self.class_name_without_kvo}"
|
201
|
-
block.call(data, status_code) if use_callback
|
202
|
+
block.call(data, status_code, response) if use_callback
|
202
203
|
end
|
203
204
|
end
|
204
205
|
end
|
@@ -240,6 +241,14 @@ module MotionPrime
|
|
240
241
|
end
|
241
242
|
|
242
243
|
module ModelSyncClassMethods
|
244
|
+
def new(data = {}, options = {})
|
245
|
+
model = super
|
246
|
+
if fetch_attributes = options[:fetch_attributes]
|
247
|
+
model.fetch_with_attributes(fetch_attributes)
|
248
|
+
end
|
249
|
+
model
|
250
|
+
end
|
251
|
+
|
243
252
|
def sync_url(url = nil, &block)
|
244
253
|
if url || block_given?
|
245
254
|
self._sync_url = url || block
|
@@ -1,7 +1,6 @@
|
|
1
1
|
motion_require "./_aliases_mixin"
|
2
2
|
motion_require "./_orientations_mixin"
|
3
3
|
motion_require "./_navigation_mixin"
|
4
|
-
motion_require "./_navigation_bar_mixin"
|
5
4
|
module MotionPrime
|
6
5
|
module ScreenBaseMixin
|
7
6
|
extend ::MotionSupport::Concern
|
@@ -10,16 +9,25 @@ module MotionPrime
|
|
10
9
|
include MotionPrime::ScreenAliasesMixin
|
11
10
|
include MotionPrime::ScreenOrientationsMixin
|
12
11
|
include MotionPrime::ScreenNavigationMixin
|
13
|
-
include MotionPrime::ScreenNavigationBarMixin
|
14
12
|
|
15
|
-
attr_accessor :parent_screen, :modal, :params, :main_section
|
13
|
+
attr_accessor :parent_screen, :modal, :params, :main_section, :options
|
16
14
|
class_attribute :current_screen
|
17
15
|
|
18
16
|
included do
|
19
17
|
define_callbacks :load
|
20
18
|
end
|
21
19
|
|
22
|
-
def
|
20
|
+
def app_delegate
|
21
|
+
UIApplication.sharedApplication.delegate
|
22
|
+
end
|
23
|
+
|
24
|
+
def show_sidebar
|
25
|
+
app_delegate.show_sidebar
|
26
|
+
end
|
27
|
+
|
28
|
+
def hide_sidebar
|
29
|
+
app_delegate.hide_sidebar
|
30
|
+
end
|
23
31
|
|
24
32
|
def on_screen_load
|
25
33
|
run_callbacks :load do
|
@@ -27,42 +35,28 @@ module MotionPrime
|
|
27
35
|
end
|
28
36
|
end
|
29
37
|
|
30
|
-
|
38
|
+
# Setup the screen, will be called when you run DMViewController.new
|
39
|
+
# @param options [hash] Options passed to setup
|
40
|
+
# @return [MotionPrime::BaseScreen] Ready to use screen
|
41
|
+
def on_create(options = {})
|
31
42
|
unless self.is_a?(UIViewController)
|
32
43
|
raise StandardError.new("ERROR: Screens must extend UIViewController.")
|
33
44
|
end
|
34
45
|
|
35
|
-
self.
|
36
|
-
|
46
|
+
self.options = options
|
47
|
+
self.params = options[:params] || {}
|
48
|
+
options.each do |k, v|
|
37
49
|
self.send("#{k}=", v) if self.respond_to?("#{k}=")
|
38
50
|
end
|
39
51
|
|
40
|
-
@wrap_in_navigation = args[:navigation]
|
41
|
-
|
42
52
|
self.on_init if respond_to?(:on_init)
|
43
53
|
self
|
44
54
|
end
|
45
55
|
|
46
|
-
def wrap_in_navigation?
|
47
|
-
@wrap_in_navigation
|
48
|
-
end
|
49
|
-
|
50
56
|
def modal?
|
51
57
|
!!self.modal
|
52
58
|
end
|
53
59
|
|
54
|
-
def has_navigation?
|
55
|
-
!navigation_controller.nil?
|
56
|
-
end
|
57
|
-
|
58
|
-
def navigation_controller
|
59
|
-
@navigation_controller ||= self.navigationController
|
60
|
-
end
|
61
|
-
|
62
|
-
def navigation_controller=(val)
|
63
|
-
@navigation_controller = val
|
64
|
-
end
|
65
|
-
|
66
60
|
def title
|
67
61
|
title = self.class.title
|
68
62
|
title = self.instance_eval(&title) if title.is_a?(Proc)
|
@@ -71,39 +65,12 @@ module MotionPrime
|
|
71
65
|
|
72
66
|
def title=(new_title)
|
73
67
|
self.class.title(new_title)
|
74
|
-
super
|
75
68
|
end
|
76
69
|
|
77
70
|
def main_controller
|
78
71
|
has_navigation? ? navigation_controller : self
|
79
72
|
end
|
80
73
|
|
81
|
-
# ACTIVITY INDICATOR
|
82
|
-
# ---------------------
|
83
|
-
|
84
|
-
def show_activity_indicator
|
85
|
-
if @activity_indicator_view.nil?
|
86
|
-
@activity_indicator_view = UIActivityIndicatorView.gray
|
87
|
-
@activity_indicator_view.center = CGPointMake(view.center.x, view.center.y - 50)
|
88
|
-
view.addSubview @activity_indicator_view
|
89
|
-
end
|
90
|
-
@activity_indicator_view.startAnimating
|
91
|
-
end
|
92
|
-
|
93
|
-
def hide_activity_indicator
|
94
|
-
return unless @activity_indicator_view
|
95
|
-
@activity_indicator_view.stopAnimating
|
96
|
-
end
|
97
|
-
|
98
|
-
def show_notice(message, time = 1.0, type = :notice)
|
99
|
-
hud_type = case type.to_s
|
100
|
-
when 'alert' then MBAlertViewHUDTypeExclamationMark
|
101
|
-
else MBAlertViewHUDTypeCheckmark
|
102
|
-
end
|
103
|
-
MBHUDView.hudWithBody message,
|
104
|
-
type: hud_type, hidesAfter: time, show: true
|
105
|
-
end
|
106
|
-
|
107
74
|
def refresh
|
108
75
|
main_section.try(:reload_data)
|
109
76
|
end
|
@@ -1,17 +1,14 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
module ScreenNavigationMixin
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
app_delegate.hide_sidebar
|
13
|
-
end
|
14
|
-
|
3
|
+
# Open screen as child for current screen if current screen have navigation or new screen is modal.
|
4
|
+
# Otherwise will create screen using app_delegate.open_screen.
|
5
|
+
# Available options:
|
6
|
+
# animated: open screen with animation.
|
7
|
+
# modal: open screen as model
|
8
|
+
|
9
|
+
# @param screen [MotionPrime::BaseScreen] Screen to be opened
|
10
|
+
# @param args [Hash] Options for opening screen
|
11
|
+
# @return [MotionPrime::BaseScreen]
|
15
12
|
def open_screen(screen, args = {})
|
16
13
|
if args[:modal] || has_navigation?
|
17
14
|
screen = setup_screen_for_open(screen, args)
|
@@ -25,8 +22,10 @@ module MotionPrime
|
|
25
22
|
else
|
26
23
|
app_delegate.open_screen(screen.main_controller)
|
27
24
|
end
|
25
|
+
screen
|
28
26
|
end
|
29
27
|
|
28
|
+
|
30
29
|
def close_screen(args = {})
|
31
30
|
args[:animated] = args.has_key?(:animated) ? args[:animated] : true
|
32
31
|
# Pop current view, maybe with arguments, if in navigation controller
|
@@ -47,13 +46,28 @@ module MotionPrime
|
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
def wrap_in_navigation?
|
50
|
+
options[:navigation]
|
51
|
+
end
|
52
|
+
|
53
|
+
def wrap_in_navigation
|
54
|
+
if wrap_in_navigation?
|
55
|
+
wrap_in_navigation!
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
59
|
+
def has_navigation?
|
60
|
+
!navigation_controller.nil?
|
61
|
+
end
|
62
|
+
|
63
|
+
def navigation_controller
|
64
|
+
@navigation_controller ||= self.navigationController
|
65
|
+
end
|
66
|
+
|
67
|
+
def navigation_controller=(val)
|
68
|
+
@navigation_controller = val
|
69
|
+
end
|
70
|
+
|
57
71
|
private
|
58
72
|
def setup_screen_for_open(screen, args = {})
|
59
73
|
# Instantiate screen if given a class
|
@@ -92,19 +106,7 @@ module MotionPrime
|
|
92
106
|
send_on_return(args)
|
93
107
|
end
|
94
108
|
|
95
|
-
def
|
96
|
-
!navigation_controller.nil?
|
97
|
-
end
|
98
|
-
|
99
|
-
def navigation_controller
|
100
|
-
@navigation_controller ||= self.navigationController
|
101
|
-
end
|
102
|
-
|
103
|
-
def navigation_controller=(val)
|
104
|
-
@navigation_controller = val
|
105
|
-
end
|
106
|
-
|
107
|
-
def add_navigation_controller
|
109
|
+
def wrap_in_navigation!
|
108
110
|
self.navigation_controller = NavigationController.alloc.initWithRootViewController(self)
|
109
111
|
end
|
110
112
|
end
|
@@ -1,12 +1,20 @@
|
|
1
1
|
motion_require '../support/dm_view_controller.rb'
|
2
2
|
motion_require '../views/layout.rb'
|
3
3
|
motion_require '../screens/_base_mixin.rb'
|
4
|
+
motion_require './extensions/_indicators_mixin'
|
5
|
+
motion_require './extensions/_navigation_bar_mixin'
|
4
6
|
motion_require '../helpers/has_authorization'
|
5
7
|
motion_require '../helpers/has_search_bar'
|
6
8
|
module MotionPrime
|
7
9
|
class BaseScreen < DMViewController
|
8
10
|
include Layout
|
9
11
|
include ScreenBaseMixin
|
12
|
+
|
13
|
+
# extensions
|
14
|
+
include ScreenIndicatorsMixin
|
15
|
+
include ScreenNavigationBarMixin
|
16
|
+
|
17
|
+
# helpers
|
10
18
|
include HasAuthorization
|
11
19
|
include HasSearchBar
|
12
20
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module MotionPrime
|
2
|
+
module ScreenIndicatorsMixin
|
3
|
+
def show_activity_indicator
|
4
|
+
if @activity_indicator_view.nil?
|
5
|
+
@activity_indicator_view = UIActivityIndicatorView.gray
|
6
|
+
@activity_indicator_view.center = CGPointMake(view.center.x, view.center.y - 50)
|
7
|
+
view.addSubview @activity_indicator_view
|
8
|
+
end
|
9
|
+
@activity_indicator_view.startAnimating
|
10
|
+
end
|
11
|
+
|
12
|
+
def hide_activity_indicator
|
13
|
+
return unless @activity_indicator_view
|
14
|
+
@activity_indicator_view.stopAnimating
|
15
|
+
end
|
16
|
+
|
17
|
+
def show_notice(message, time = 1.0, type = :notice)
|
18
|
+
hud_type = case type.to_s
|
19
|
+
when 'alert' then MBAlertViewHUDTypeExclamationMark
|
20
|
+
else MBAlertViewHUDTypeCheckmark
|
21
|
+
end
|
22
|
+
MBHUDView.hudWithBody message,
|
23
|
+
type: hud_type, hidesAfter: time, show: true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
File without changes
|
@@ -60,7 +60,7 @@ module MotionPrime
|
|
60
60
|
def prepare_controller(controller)
|
61
61
|
controller = setup_screen_for_open(controller, {})
|
62
62
|
if content_controller.nil?
|
63
|
-
controller.
|
63
|
+
controller.wrap_in_navigation if controller.respond_to?(:wrap_in_navigation)
|
64
64
|
controller.send(:on_screen_load) if controller.respond_to?(:on_screen_load)
|
65
65
|
controller = controller.main_controller if controller.respond_to?(:main_controller)
|
66
66
|
else
|
@@ -83,7 +83,7 @@ module MotionPrime
|
|
83
83
|
index = opts.delete(:at)
|
84
84
|
options = build_options_for_element(opts)
|
85
85
|
options[:name] ||= key
|
86
|
-
options[:type] ||= options[:text] ? :label : :view
|
86
|
+
options[:type] ||= (options[:text] || options[:attributed_text_options]) ? :label : :view
|
87
87
|
element = MotionPrime::BaseElement.factory(options.delete(:type), options)
|
88
88
|
if index
|
89
89
|
self.elements = Hash[self.elements.to_a.insert index, [key, element]]
|
@@ -147,7 +147,7 @@ module MotionPrime
|
|
147
147
|
end
|
148
148
|
|
149
149
|
def keyboard_will_show
|
150
|
-
return if table_view.contentSize.height + table_view.top <= UIScreen.mainScreen.bounds.size.height
|
150
|
+
return if table_view.contentSize.height + table_view.top <= UIScreen.mainScreen.bounds.size.height - KEYBOARD_HEIGHT_PORTRAIT
|
151
151
|
current_inset = table_view.contentInset
|
152
152
|
current_inset.bottom = KEYBOARD_HEIGHT_PORTRAIT + (self.table_element.computed_options[:bottom_content_offset] || 0)
|
153
153
|
table_view.contentInset = current_inset
|
@@ -164,13 +164,16 @@ module MotionPrime
|
|
164
164
|
def on_input_edit(text_field); end
|
165
165
|
def on_input_return(text_field)
|
166
166
|
text_field.resignFirstResponder
|
167
|
-
end
|
167
|
+
end
|
168
168
|
def textFieldShouldReturn(text_field)
|
169
169
|
on_input_return(text_field)
|
170
170
|
end
|
171
171
|
def textFieldDidBeginEditing(text_field)
|
172
172
|
on_input_edit(text_field)
|
173
173
|
end
|
174
|
+
def textViewDidBeginEditing(text_view)
|
175
|
+
on_input_edit(text_view)
|
176
|
+
end
|
174
177
|
|
175
178
|
def textView(text_view, shouldChangeTextInRange:range, replacementText:string)
|
176
179
|
limit = (self.class.text_view_limits || {}).find do |field_name, limit|
|
@@ -56,8 +56,8 @@ module MotionPrime
|
|
56
56
|
# focus on text field
|
57
57
|
return unless begin_editing
|
58
58
|
elements.values.each do |element|
|
59
|
-
if element.view.is_a?(UITextField)
|
60
|
-
element.view.becomeFirstResponder
|
59
|
+
if element.view.is_a?(UITextField) || element.view.is_a?(UITextView)
|
60
|
+
element.view.becomeFirstResponder and return
|
61
61
|
end
|
62
62
|
end
|
63
63
|
self
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module MotionPrime
|
2
|
+
module SupportPaddingAttribute
|
3
|
+
extend ::MotionSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
attr_accessor :paddingLeft, :paddingRight, :paddingTop, :paddingBottom, :padding
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def default_padding_top
|
11
|
+
0
|
12
|
+
end
|
13
|
+
|
14
|
+
def default_padding_left
|
15
|
+
0
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_padding_right
|
19
|
+
0
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_padding_bottom
|
23
|
+
0
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def padding_left
|
28
|
+
self.paddingLeft || self.padding || self.class.default_padding_left
|
29
|
+
end
|
30
|
+
|
31
|
+
def padding_right
|
32
|
+
self.paddingRight || self.padding || self.class.default_padding_right
|
33
|
+
end
|
34
|
+
|
35
|
+
def padding_top
|
36
|
+
self.paddingTop || self.padding || self.class.default_padding_top
|
37
|
+
end
|
38
|
+
|
39
|
+
def padding_bottom
|
40
|
+
self.paddingBottom || self.padding || self.class.default_padding_bottom
|
41
|
+
end
|
42
|
+
|
43
|
+
def padding_insets
|
44
|
+
UIEdgeInsetsMake(padding_top, padding_left, padding_bottom, padding_right)
|
45
|
+
end
|
46
|
+
|
47
|
+
def apply_padding(rect)
|
48
|
+
return unless apply_padding?
|
49
|
+
apply_padding!(rect)
|
50
|
+
end
|
51
|
+
|
52
|
+
def apply_padding!(rect)
|
53
|
+
raise "requires implementation"
|
54
|
+
end
|
55
|
+
|
56
|
+
def apply_padding?
|
57
|
+
![padding_top, padding_left, padding_right, padding_bottom].all?(&:zero?)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|