ProMotion 0.6.5 → 0.7.0

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 (56) hide show
  1. data/README.md +79 -502
  2. data/Rakefile +30 -0
  3. data/app/app_delegate.rb +3 -1
  4. data/lib/ProMotion.rb +1 -1
  5. data/lib/ProMotion/cocoatouch/TableViewCell.rb +5 -1
  6. data/lib/ProMotion/delegate/delegate.rb +16 -0
  7. data/lib/ProMotion/delegate/delegate_helper.rb +88 -0
  8. data/lib/ProMotion/delegate/delegate_notifications.rb +61 -0
  9. data/lib/ProMotion/helpers/console.rb +3 -3
  10. data/lib/ProMotion/helpers/logger.rb +15 -15
  11. data/lib/ProMotion/helpers/view_helper.rb +7 -5
  12. data/lib/ProMotion/push_notifications/push_notification.rb +51 -0
  13. data/lib/ProMotion/screen_helpers/screen_elements.rb +2 -2
  14. data/lib/ProMotion/screen_helpers/screen_navigation.rb +5 -1
  15. data/lib/ProMotion/screen_helpers/screen_tabs.rb +2 -2
  16. data/lib/ProMotion/screens/_compatibility/formotion_screen.rb +65 -0
  17. data/lib/ProMotion/screens/_screen_module.rb +33 -20
  18. data/lib/ProMotion/screens/_table_screen_module.rb +4 -4
  19. data/lib/ProMotion/{screen_helpers → screens}/_tables/_refreshable_table.rb +2 -2
  20. data/lib/ProMotion/{screen_helpers → screens}/_tables/_searchable_table.rb +27 -34
  21. data/lib/ProMotion/screens/_tables/_sectioned_table.rb +5 -0
  22. data/lib/ProMotion/screens/_tables/_table.rb +149 -0
  23. data/lib/ProMotion/screens/_tables/grouped_table.rb +16 -0
  24. data/lib/ProMotion/screens/_tables/plain_table.rb +17 -0
  25. data/lib/ProMotion/screens/_tables/table_data.rb +148 -0
  26. data/lib/ProMotion/screens/_tables/table_view_cell_module.rb +156 -0
  27. data/lib/ProMotion/screens/table_screen.rb +3 -2
  28. data/lib/ProMotion/version.rb +1 -1
  29. data/spec/functional/func_screen_spec.rb +66 -0
  30. data/spec/functional/func_split_screen_spec.rb +66 -0
  31. data/spec/functional/func_table_screen_spec.rb +52 -0
  32. data/spec/helpers/functional_screen.rb +15 -0
  33. data/spec/helpers/table_screen.rb +32 -8
  34. data/spec/helpers/table_screen_refreshable.rb +1 -1
  35. data/spec/helpers/table_screen_searchable.rb +1 -1
  36. data/spec/helpers/test_delegate.rb +2 -0
  37. data/spec/unit/delegate_spec.rb +38 -0
  38. data/spec/{ios_version_spec.rb → unit/ios_version_spec.rb} +0 -0
  39. data/spec/{logger_spec.rb → unit/logger_spec.rb} +0 -0
  40. data/spec/{main_spec.rb → unit/main_spec.rb} +0 -0
  41. data/spec/{screen_helpers_spec.rb → unit/screen_helpers_spec.rb} +14 -6
  42. data/spec/{screen_module_spec.rb → unit/screen_module_spec.rb} +0 -0
  43. data/spec/{screen_spec.rb → unit/screen_spec.rb} +21 -3
  44. data/spec/{split_screen_in_tab_bar_spec.rb → unit/split_screen_in_tab_bar_spec.rb} +0 -0
  45. data/spec/{split_screen_open_screen_spec.rb → unit/split_screen_open_screen_spec.rb} +0 -0
  46. data/spec/{split_screen_spec.rb → unit/split_screen_spec.rb} +0 -0
  47. data/spec/unit/tables/table_module_spec.rb +108 -0
  48. data/spec/unit/tables/table_screen_spec.rb +92 -0
  49. data/spec/unit/tables/table_view_cell_spec.rb +106 -0
  50. data/spec/{view_helper_spec.rb → unit/view_helper_spec.rb} +0 -0
  51. metadata +50 -29
  52. data/lib/ProMotion/delegate.rb +0 -63
  53. data/lib/ProMotion/screen_helpers/_tables/_sectioned_table.rb +0 -270
  54. data/lib/ProMotion/screen_helpers/_tables/grouped_table.rb +0 -14
  55. data/lib/ProMotion/screen_helpers/_tables/plain_table.rb +0 -15
  56. data/spec/table_screen_spec.rb +0 -72
data/Rakefile CHANGED
@@ -19,3 +19,33 @@ Motion::Project::App.setup do |app|
19
19
 
20
20
  app.detect_dependencies = true
21
21
  end
22
+
23
+ def all_files
24
+ App.config.spec_files
25
+ end
26
+
27
+ def functional_files
28
+ Dir.glob('./spec/functional/*.rb')
29
+ end
30
+
31
+ def unit_files
32
+ Dir.glob('./spec/unit/*.rb')
33
+ end
34
+
35
+ namespace :spec do
36
+ task :unit do
37
+ App.config.spec_mode = true
38
+ spec_files = all_files
39
+ spec_files -= functional_files
40
+ App.config.instance_variable_set("@spec_files", spec_files)
41
+ Rake::Task["simulator"].invoke
42
+ end
43
+
44
+ task :functional do
45
+ App.config.spec_mode = true
46
+ spec_files = all_files
47
+ spec_files -= unit_files
48
+ App.config.instance_variable_set("@spec_files", spec_files)
49
+ Rake::Task["simulator"].invoke
50
+ end
51
+ end
data/app/app_delegate.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  class AppDelegate
2
+
2
3
  def on_load(app, options)
3
- open BasicScreen
4
+ open BasicScreen.new(nav_bar: true)
4
5
  end
6
+
5
7
  end
data/lib/ProMotion.rb CHANGED
@@ -6,7 +6,7 @@ require "ProMotion/version"
6
6
 
7
7
  Motion::Project::App.setup do |app|
8
8
  original_files = app.files
9
- delegate = File.join(File.dirname(__FILE__), 'ProMotion/delegate.rb')
9
+ delegate = File.join(File.dirname(__FILE__), 'ProMotion/delegate/delegate.rb')
10
10
  promotion_files = FileList[File.join(File.dirname(__FILE__), 'ProMotion/**/*.rb')].exclude(delegate).to_a
11
11
  app.files = (promotion_files << delegate) + original_files
12
12
  end
@@ -1,7 +1,10 @@
1
1
  module ProMotion
2
2
  class TableViewCell < UITableViewCell
3
+ include TableViewCellModule
4
+
3
5
  attr_accessor :image_size
4
6
 
7
+ # TODO: Is this necessary?
5
8
  def layoutSubviews
6
9
  super
7
10
 
@@ -12,5 +15,6 @@ module ProMotion
12
15
  self.imageView.frame = CGRectInset(f, size_inset_x, size_inset_y)
13
16
  end
14
17
  end
18
+
15
19
  end
16
- end
20
+ end
@@ -0,0 +1,16 @@
1
+ module ProMotion
2
+ class Delegate
3
+
4
+ include ProMotion::ScreenTabs
5
+ include ProMotion::SplitScreen if NSBundle.mainBundle.infoDictionary["UIDeviceFamily"].include?("2") # Only with iPad
6
+ include DelegateHelper
7
+ include DelegateNotifications
8
+
9
+ end
10
+
11
+ class AppDelegateParent < Delegate
12
+ def self.inherited(klass)
13
+ PM.logger.deprecated "PM::AppDelegateParent is deprecated. Use PM::Delegate."
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,88 @@
1
+ module ProMotion
2
+ module DelegateHelper
3
+
4
+ attr_accessor :window, :aps_notification, :home_screen
5
+
6
+ def application(application, didFinishLaunchingWithOptions:launch_options)
7
+
8
+ apply_status_bar
9
+
10
+ on_load application, launch_options
11
+
12
+ check_for_push_notification launch_options
13
+
14
+ true
15
+
16
+ end
17
+
18
+ def applicationWillTerminate(application)
19
+
20
+ on_unload if respond_to?(:on_unload)
21
+
22
+ end
23
+
24
+ def app_delegate
25
+ self
26
+ end
27
+
28
+ def app_window
29
+ self.window
30
+ end
31
+
32
+ def ui_window
33
+ (defined?(Motion) && defined?(Motion::Xray) && defined?(Motion::Xray::XrayWindow)) ? Motion::Xray::XrayWindow : UIWindow
34
+ end
35
+
36
+ def open_screen(screen, args={})
37
+
38
+ screen = screen.new if screen.respond_to?(:new)
39
+ screen.send(:on_load) if screen.respond_to?(:on_load)
40
+
41
+ self.home_screen = screen
42
+
43
+ self.window ||= self.ui_window.alloc.initWithFrame(UIScreen.mainScreen.bounds)
44
+ self.window.rootViewController = screen.pm_main_controller
45
+ self.window.makeKeyAndVisible
46
+
47
+ end
48
+ alias :open :open_screen
49
+ alias :open_root_screen :open_screen
50
+ alias :home :open_screen
51
+
52
+ def apply_status_bar
53
+ self.class.send(:apply_status_bar)
54
+ end
55
+
56
+ def status_bar?
57
+ UIApplication.sharedApplication.statusBarHidden
58
+ end
59
+
60
+ module ClassMethods
61
+
62
+ def status_bar(visible = true, opts={})
63
+ @status_bar_visible = visible
64
+ @status_bar_opts = opts
65
+ end
66
+
67
+ def apply_status_bar
68
+ @status_bar_visible ||= true
69
+ @status_bar_opts ||= { animation: :none }
70
+ UIApplication.sharedApplication.setStatusBarHidden(!@status_bar_visible, withAnimation:status_bar_animation(@status_bar_opts[:animation]))
71
+ end
72
+
73
+ def status_bar_animation(opt)
74
+ {
75
+ fade: UIStatusBarAnimationFade,
76
+ slide: UIStatusBarAnimationSlide,
77
+ none: UIStatusBarAnimationNone
78
+ }[opt] || UIStatusBarAnimationNone
79
+ end
80
+
81
+ end
82
+
83
+ def self.included(base)
84
+ base.extend(ClassMethods)
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,61 @@
1
+ module ProMotion
2
+ module DelegateNotifications
3
+
4
+ attr_accessor :aps_notification
5
+
6
+ def check_for_push_notification(options)
7
+ if options && options[UIApplicationLaunchOptionsRemoteNotificationKey]
8
+ received_push_notification options[UIApplicationLaunchOptionsRemoteNotificationKey]
9
+ end
10
+ end
11
+
12
+ def register_for_push_notifications(*notification_types)
13
+ notification_types = Array.new(notification_types)
14
+ notification_types = [ :badge, :sound, :alert, :newsstand ] if notification_types.include?(:all)
15
+
16
+ types = UIRemoteNotificationTypeNone
17
+ types = types | UIRemoteNotificationTypeBadge if notification_types.include?(:badge)
18
+ types = types | UIRemoteNotificationTypeSound if notification_types.include?(:sound)
19
+ types = types | UIRemoteNotificationTypeAlert if notification_types.include?(:alert)
20
+ types = types | UIRemoteNotificationTypeNewsstandContentAvailability if notification_types.include?(:newsstand)
21
+
22
+ UIApplication.sharedApplication.registerForRemoteNotificationTypes types
23
+ end
24
+
25
+ def unregister_for_push_notifications
26
+ UIApplication.sharedApplication.unregisterForRemoteNotifications
27
+ end
28
+
29
+ def registered_push_notifications
30
+ mask = UIApplication.sharedApplication.enabledRemoteNotificationTypes
31
+ types = []
32
+
33
+ types << :badge if mask & UIRemoteNotificationTypeBadge
34
+ types << :sound if mask & UIRemoteNotificationTypeSound
35
+ types << :alert if mask & UIRemoteNotificationTypeAlert
36
+ types << :newsstand if mask & UIRemoteNotificationTypeNewsstandContentAvailability
37
+
38
+ types
39
+ end
40
+
41
+ def received_push_notification(notification)
42
+ @aps_notification = PM::PushNotification.new(notification)
43
+ on_push_notification(@aps_notification) if respond_to?(:on_push_notification)
44
+ end
45
+
46
+ # CocoaTouch
47
+
48
+ def application(application, didRegisterForRemoteNotificationsWithDeviceToken:device_token)
49
+ on_push_registration(device_token, nil) if respond_to?(:on_push_registration)
50
+ end
51
+
52
+ def application(application, didFailToRegisterForRemoteNotificationsWithError:error)
53
+ on_push_registration(nil, error) if respond_to?(:on_push_registration)
54
+ end
55
+
56
+ def application(application, didReceiveRemoteNotification:notification)
57
+ received_push_notification(notification)
58
+ end
59
+
60
+ end
61
+ end
@@ -8,19 +8,19 @@ module ProMotion
8
8
 
9
9
  class << self
10
10
  def log(log, with_color:color)
11
- return if RUBYMOTION_ENV == "test"
11
+ return if defined?(RUBYMOTION_ENV) && RUBYMOTION_ENV == "test"
12
12
  PM.logger.deprecated "ProMotion::Console.log is deprecated. Use PM.logger (see README)"
13
13
  puts color[0] + NAME + log + color[1]
14
14
  end
15
15
 
16
16
  def log(log, withColor:color)
17
- return if RUBYMOTION_ENV == "test"
17
+ return if defined?(RUBYMOTION_ENV) && RUBYMOTION_ENV == "test"
18
18
  PM.logger.deprecated "ProMotion::Console.log is deprecated. Use PM.logger (see README)"
19
19
  self.log(log, with_color:color)
20
20
  end
21
21
 
22
22
  def log(log)
23
- return if RUBYMOTION_ENV == "test"
23
+ return if defined?(RUBYMOTION_ENV) && RUBYMOTION_ENV == "test"
24
24
  PM.logger.deprecated "ProMotion::Console.log is deprecated. Use PM.logger (see README)"
25
25
  log(log, with_color: DEFAULT_COLOR)
26
26
  end
@@ -1,9 +1,9 @@
1
1
  module ProMotion
2
2
  class Logger
3
3
  attr_accessor :level
4
-
4
+
5
5
  NAME = "ProMotion::Logger: "
6
-
6
+
7
7
  COLORS = {
8
8
  default: [ '', '' ],
9
9
  red: [ "\e[0;31m", "\e[0m" ],
@@ -13,7 +13,7 @@ module ProMotion
13
13
  purple: [ "\e[0;35m", "\e[0m" ],
14
14
  cyan: [ "\e[0;36m", "\e[0m" ]
15
15
  }
16
-
16
+
17
17
  LEVELS = {
18
18
  off: [],
19
19
  error: [:error],
@@ -22,17 +22,17 @@ module ProMotion
22
22
  verbose: [:error, :warn, :info, :debug, :verbose],
23
23
  debug: [:error, :warn, :info, :debug, :verbose]
24
24
  }
25
-
25
+
26
26
  def level
27
27
  @level ||= :debug
28
28
  end
29
-
29
+
30
30
  def levels
31
31
  LEVELS[self.level] || []
32
32
  end
33
-
33
+
34
34
  # Usage: PM.logger.log("ERROR", "message here", :red)
35
- def log(label, message_text, color)
35
+ def log(label, message_text, color)
36
36
  return if RUBYMOTION_ENV == "test"
37
37
  color = COLORS[color] || COLORS[:default]
38
38
  puts color[0] + NAME + "[#{label}] #{message_text}" + color[1]
@@ -40,26 +40,26 @@ module ProMotion
40
40
 
41
41
  def error(message)
42
42
  self.log('ERROR', message, :red) if self.levels.include?(:error)
43
- end
43
+ end
44
44
 
45
45
  def deprecated(message)
46
46
  self.log('DEPRECATED', message, :yellow) if self.levels.include?(:warn)
47
- end
47
+ end
48
48
 
49
- def warn(message)
49
+ def warn(message)
50
50
  self.log('WARN', message, :yellow) if self.levels.include?(:warn)
51
51
  end
52
-
53
- def debug(message)
52
+
53
+ def debug(message)
54
54
  self.log('DEBUG', message, :purple) if self.levels.include?(:debug)
55
- end
55
+ end
56
56
 
57
- def info(message)
57
+ def info(message)
58
58
  self.log('INFO', message, :green) if self.levels.include?(:info)
59
59
  end
60
60
 
61
61
  end
62
-
62
+
63
63
  module_function
64
64
 
65
65
  def logger
@@ -6,13 +6,15 @@ module ProMotion
6
6
  end
7
7
 
8
8
  def set_attribute(element, k, v)
9
+ return element unless element
10
+
9
11
  if v.is_a?(Hash) && element.respond_to?(k)
10
12
  sub_element = element.send(k)
11
- set_attributes sub_element, v
12
- elsif v.is_a?(Array) && element.respond_to?("#{k}")
13
- element.send("#{k}", *v)
13
+ set_attributes(sub_element, v) if sub_element
14
14
  elsif element.respond_to?("#{k}=")
15
15
  element.send("#{k}=", v)
16
+ elsif v.is_a?(Array) && element.respond_to?("#{k}") && element.method("#{k}").arity == v.length
17
+ element.send("#{k}", *v)
16
18
  else
17
19
  # Doesn't respond. Check if snake case.
18
20
  if k.to_s.include?("_")
@@ -48,7 +50,7 @@ module ProMotion
48
50
  end
49
51
 
50
52
  def frame_from_array(array)
51
- PM.logger.deprecated "`frame_from_array` is deprecated and will be removed. Use RubyMotion's built-in [[x, y], [width, height]]."
53
+ PM.logger.deprecated "`frame_from_array` is deprecated and will be removed. Use RubyMotion's built-in [[x, y], [width, height]] or CGRectMake(x, y, w, h)."
52
54
  return CGRectMake(array[0], array[1], array[2], array[3]) if array.length == 4
53
55
  PM.logger.error "frame_from_array expects an array with four elements: [x, y, width, height]"
54
56
  CGRectZero.dup
@@ -68,4 +70,4 @@ module ProMotion
68
70
  end
69
71
 
70
72
  end
71
- end
73
+ end
@@ -0,0 +1,51 @@
1
+ module ProMotion
2
+ class PushNotification
3
+
4
+ attr_accessor :notification
5
+
6
+ def initialize(n)
7
+ self.notification = n
8
+ end
9
+
10
+ def to_s
11
+ self.notification.inspect
12
+ end
13
+
14
+ def to_json
15
+ PM.logger.warn "PM::PushNotification.to_json not implemented yet."
16
+ end
17
+
18
+ def aps
19
+ self.notification["aps"]
20
+ end
21
+
22
+ def alert
23
+ aps["alert"] if aps
24
+ end
25
+
26
+ def badge
27
+ aps["badge"] if aps
28
+ end
29
+
30
+ def sound
31
+ aps["sound"] if aps
32
+ end
33
+
34
+ # For testing from the REPL
35
+ # > PM::PushNotification.simulate alert: "My test message", badge: 4
36
+ def self.simulate(args = {})
37
+ UIApplication.sharedApplication.delegate.on_push_notification self.fake_notification(args)
38
+ end
39
+
40
+ def self.fake_notification(args = {})
41
+ self.new({
42
+ "aps" => {
43
+ "alert" => args[:alert] || "Test Push Notification",
44
+ "badge" => args[:badge] || 2,
45
+ "sound" => args[:sound] || "default"
46
+ }
47
+ })
48
+ end
49
+
50
+ end
51
+ end
@@ -14,13 +14,13 @@ module ProMotion
14
14
  end
15
15
  alias :remove_element :remove
16
16
  alias :remove_view :remove
17
-
17
+
18
18
  def add_to(parent_element, element, attrs = {})
19
+ parent_element.addSubview element
19
20
  if attrs && attrs.length > 0
20
21
  set_attributes(element, attrs)
21
22
  set_easy_attributes(parent_element, element, attrs)
22
23
  end
23
- parent_element.addSubview element
24
24
  element
25
25
  end
26
26