ProMotion 0.6.5 → 0.7.0

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