mirror of
https://github.com/zhigang1992/ProMotion.git
synced 2026-06-01 19:49:13 +08:00
Merge pull request #91 from clearsightstudio/feature/delegate_improvements
PM::Delegate improvements, PushNotification object & methods
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
class AppDelegate
|
||||
|
||||
def on_load(app, options)
|
||||
open BasicScreen.new(nav_bar: true)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ require "ProMotion/version"
|
||||
|
||||
Motion::Project::App.setup do |app|
|
||||
original_files = app.files
|
||||
delegate = File.join(File.dirname(__FILE__), 'ProMotion/delegate.rb')
|
||||
delegate = File.join(File.dirname(__FILE__), 'ProMotion/delegate/delegate.rb')
|
||||
promotion_files = FileList[File.join(File.dirname(__FILE__), 'ProMotion/**/*.rb')].exclude(delegate).to_a
|
||||
app.files = (promotion_files << delegate) + original_files
|
||||
end
|
||||
@@ -1,63 +0,0 @@
|
||||
module ProMotion
|
||||
class Delegate
|
||||
include ProMotion::ScreenTabs
|
||||
include ProMotion::SplitScreen if NSBundle.mainBundle.infoDictionary["UIDeviceFamily"].include?("2") # Only with iPad
|
||||
attr_accessor :window
|
||||
|
||||
def application(application, didFinishLaunchingWithOptions:launch_options)
|
||||
unless self.respond_to?(:on_load)
|
||||
PM.logger.error "Your AppDelegate (usually in app_delegate.rb) needs an on_load(application, options) method."
|
||||
end
|
||||
|
||||
on_load(application, launch_options)
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def app_delegate
|
||||
UIApplication.sharedApplication.delegate
|
||||
end
|
||||
|
||||
def app_window
|
||||
self.app_delegate.window
|
||||
end
|
||||
|
||||
def home(screen)
|
||||
screen = screen.new if screen.respond_to?(:new)
|
||||
@home_screen = screen
|
||||
end
|
||||
|
||||
def load_root_screen(new_screen)
|
||||
new_screen = new_screen.pm_main_controller
|
||||
|
||||
self.window ||= self.ui_window.alloc.initWithFrame(UIScreen.mainScreen.bounds)
|
||||
self.window.rootViewController = new_screen
|
||||
self.window.makeKeyAndVisible
|
||||
end
|
||||
|
||||
def ui_window
|
||||
(defined?(Motion) && defined?(Motion::Xray) && defined?(Motion::Xray::XrayWindow)) ? Motion::Xray::XrayWindow : UIWindow
|
||||
end
|
||||
|
||||
def open_screen(screen, args={})
|
||||
home(screen)
|
||||
open_home_screen
|
||||
end
|
||||
alias :open :open_screen
|
||||
alias :open_root_screen :open_screen
|
||||
|
||||
def open_home_screen
|
||||
get_home_screen.send(:on_load) if get_home_screen.respond_to?(:on_load)
|
||||
load_root_screen get_home_screen
|
||||
end
|
||||
|
||||
def get_home_screen
|
||||
@home_screen
|
||||
end
|
||||
|
||||
def has_home_screen
|
||||
@home_screen.nil? == false
|
||||
end
|
||||
end
|
||||
class AppDelegateParent < Delegate; end # For backwards compatibility
|
||||
end
|
||||
36
lib/ProMotion/delegate/delegate.rb
Normal file
36
lib/ProMotion/delegate/delegate.rb
Normal file
@@ -0,0 +1,36 @@
|
||||
module ProMotion
|
||||
class Delegate
|
||||
|
||||
include ProMotion::ScreenTabs
|
||||
include ProMotion::SplitScreen if NSBundle.mainBundle.infoDictionary["UIDeviceFamily"].include?("2") # Only with iPad
|
||||
include DelegateHelper
|
||||
include DelegateNotifications
|
||||
|
||||
attr_accessor :window, :aps_notification
|
||||
|
||||
def application(application, didFinishLaunchingWithOptions:launch_options)
|
||||
|
||||
apply_status_bar
|
||||
|
||||
on_load application, launch_options
|
||||
|
||||
check_for_notification launch_options
|
||||
|
||||
true
|
||||
|
||||
end
|
||||
|
||||
def applicationWillTerminate(application)
|
||||
|
||||
on_unload if respond_to?(:on_unload)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class AppDelegateParent < Delegate
|
||||
def self.inherited(klass)
|
||||
PM.logger.deprecated "PM::AppDelegateParent is deprecated. Use PM::Delegate."
|
||||
end
|
||||
end
|
||||
end
|
||||
68
lib/ProMotion/delegate/delegate_helper.rb
Normal file
68
lib/ProMotion/delegate/delegate_helper.rb
Normal file
@@ -0,0 +1,68 @@
|
||||
module ProMotion
|
||||
module DelegateHelper
|
||||
|
||||
def app_delegate
|
||||
self
|
||||
end
|
||||
|
||||
def app_window
|
||||
self.window
|
||||
end
|
||||
|
||||
def ui_window
|
||||
(defined?(Motion) && defined?(Motion::Xray) && defined?(Motion::Xray::XrayWindow)) ? Motion::Xray::XrayWindow : UIWindow
|
||||
end
|
||||
|
||||
def open_screen(screen, args={})
|
||||
|
||||
screen = screen.new if screen.respond_to?(:new)
|
||||
screen.send(:on_load) if screen.respond_to?(:on_load)
|
||||
|
||||
@home_screen = screen
|
||||
|
||||
self.window ||= self.ui_window.alloc.initWithFrame(UIScreen.mainScreen.bounds)
|
||||
self.window.rootViewController = screen.pm_main_controller
|
||||
self.window.makeKeyAndVisible
|
||||
|
||||
end
|
||||
alias :open :open_screen
|
||||
alias :open_root_screen :open_screen
|
||||
alias :home :open_screen
|
||||
|
||||
def apply_status_bar
|
||||
self.class.send(:apply_status_bar)
|
||||
end
|
||||
|
||||
def status_bar?
|
||||
UIApplication.sharedApplication.statusBarHidden
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
|
||||
def status_bar(visible = true, opts={})
|
||||
@status_bar_visible = visible
|
||||
@status_bar_opts = opts
|
||||
end
|
||||
|
||||
def apply_status_bar
|
||||
@status_bar_visible ||= true
|
||||
@status_bar_opts ||= { animation: :none }
|
||||
UIApplication.sharedApplication.setStatusBarHidden(!@status_bar_visible, withAnimation:status_bar_animation(@status_bar_opts[:animation]))
|
||||
end
|
||||
|
||||
def status_bar_animation(opt)
|
||||
{
|
||||
fade: UIStatusBarAnimationFade,
|
||||
slide: UIStatusBarAnimationSlide,
|
||||
none: UIStatusBarAnimationNone
|
||||
}[opt] || UIStatusBarAnimationNone
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def self.included(base)
|
||||
base.extend(ClassMethods)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
61
lib/ProMotion/delegate/delegate_notifications.rb
Normal file
61
lib/ProMotion/delegate/delegate_notifications.rb
Normal file
@@ -0,0 +1,61 @@
|
||||
module ProMotion
|
||||
module DelegateNotifications
|
||||
|
||||
attr_accessor :aps_notification
|
||||
|
||||
def check_for_notification(options)
|
||||
if options && options[UIApplicationLaunchOptionsRemoteNotificationKey]
|
||||
received_notification options[UIApplicationLaunchOptionsRemoteNotificationKey]
|
||||
end
|
||||
end
|
||||
|
||||
def register_for_notifications(*notification_types)
|
||||
notification_types = Array.new(notification_types)
|
||||
notification_types = [ :badge, :sound, :alert, :newsstand ] if notification_types.include?(:all)
|
||||
|
||||
types = UIRemoteNotificationTypeNone
|
||||
types = types | UIRemoteNotificationTypeBadge if notification_types.include?(:badge)
|
||||
types = types | UIRemoteNotificationTypeSound if notification_types.include?(:sound)
|
||||
types = types | UIRemoteNotificationTypeAlert if notification_types.include?(:alert)
|
||||
types = types | UIRemoteNotificationTypeNewsstandContentAvailability if notification_types.include?(:newsstand)
|
||||
|
||||
UIApplication.sharedApplication.registerForRemoteNotificationTypes types
|
||||
end
|
||||
|
||||
def unregister_for_notifications
|
||||
UIApplication.sharedApplication.unregisterForRemoteNotifications
|
||||
end
|
||||
|
||||
def registered_notifications
|
||||
mask = UIApplication.sharedApplication.enabledRemoteNotificationTypes
|
||||
types = []
|
||||
|
||||
types << :badge if mask & UIRemoteNotificationTypeBadge
|
||||
types << :sound if mask & UIRemoteNotificationTypeSound
|
||||
types << :alert if mask & UIRemoteNotificationTypeAlert
|
||||
types << :newsstand if mask & UIRemoteNotificationTypeNewsstandContentAvailability
|
||||
|
||||
types
|
||||
end
|
||||
|
||||
def received_notification(notification)
|
||||
@aps_notification = PM::PushNotification.new(notification)
|
||||
on_notification(@aps_notification) if respond_to?(:on_notification)
|
||||
end
|
||||
|
||||
# CocoaTouch
|
||||
|
||||
def application(application, didRegisterForRemoteNotificationsWithDeviceToken:device_token)
|
||||
on_registration(device_token, nil) if respond_to?(:on_registration)
|
||||
end
|
||||
|
||||
def application(application, didFailToRegisterForRemoteNotificationsWithError:error)
|
||||
on_registration(nil, error) if respond_to?(:on_registration)
|
||||
end
|
||||
|
||||
def application(application, didReceiveRemoteNotification:notification)
|
||||
received_notification(notification)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -50,7 +50,7 @@ module ProMotion
|
||||
end
|
||||
|
||||
def frame_from_array(array)
|
||||
PM.logger.deprecated "`frame_from_array` is deprecated and will be removed. Use RubyMotion's built-in [[x, y], [width, height]]."
|
||||
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)."
|
||||
return CGRectMake(array[0], array[1], array[2], array[3]) if array.length == 4
|
||||
PM.logger.error "frame_from_array expects an array with four elements: [x, y, width, height]"
|
||||
CGRectZero.dup
|
||||
|
||||
51
lib/ProMotion/push_notifications/push_notification.rb
Normal file
51
lib/ProMotion/push_notifications/push_notification.rb
Normal file
@@ -0,0 +1,51 @@
|
||||
module ProMotion
|
||||
class PushNotification
|
||||
|
||||
attr_accessor :notification
|
||||
|
||||
def initialize(n)
|
||||
self.notification = n
|
||||
end
|
||||
|
||||
def to_s
|
||||
self.notification.inspect
|
||||
end
|
||||
|
||||
def to_json
|
||||
PM.logger.warn "PM::PushNotification.to_json not implemented yet."
|
||||
end
|
||||
|
||||
def aps
|
||||
self.notification["aps"]
|
||||
end
|
||||
|
||||
def alert
|
||||
aps["alert"] if aps
|
||||
end
|
||||
|
||||
def badge
|
||||
aps["badge"] if aps
|
||||
end
|
||||
|
||||
def sound
|
||||
aps["sound"] if aps
|
||||
end
|
||||
|
||||
# For testing from the REPL
|
||||
# > PM::PushNotification.simulate alert: "My test message", badge: 4
|
||||
def self.simulate(args = {})
|
||||
UIApplication.sharedApplication.delegate.on_notification self.fake_notification(args)
|
||||
end
|
||||
|
||||
def self.fake_notification(args = {})
|
||||
self.new({
|
||||
"aps" => {
|
||||
"alert" => args[:alert] || "Test Push Notification",
|
||||
"badge" => args[:badge] || 2,
|
||||
"sound" => args[:sound] || "default"
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -52,7 +52,7 @@ module ProMotion
|
||||
args ||= {}
|
||||
args[:animated] ||= true
|
||||
|
||||
if self.is_modal?
|
||||
if self.modal?
|
||||
close_modal_screen args
|
||||
|
||||
elsif self.navigation_controller
|
||||
|
||||
@@ -34,9 +34,9 @@ module ProMotion
|
||||
def open_tab_bar(*screens)
|
||||
tab_bar = tab_bar_controller(*screens)
|
||||
|
||||
a = self.respond_to?(:load_root_screen) ? self : UIApplication.sharedApplication.delegate
|
||||
a = self.respond_to?(:open_root_screen) ? self : UIApplication.sharedApplication.delegate
|
||||
|
||||
a.load_root_screen(tab_bar)
|
||||
a.open_root_screen(tab_bar)
|
||||
tab_bar
|
||||
end
|
||||
|
||||
|
||||
@@ -27,13 +27,23 @@ module ProMotion
|
||||
end
|
||||
|
||||
def is_modal?
|
||||
PM.logger.deprecated "`is_modal?` is deprecated. Use `modal?`."
|
||||
modal?
|
||||
end
|
||||
|
||||
def modal?
|
||||
self.modal == true
|
||||
end
|
||||
|
||||
def has_nav_bar?
|
||||
self.navigation_controller.nil? != true
|
||||
PM.logger.deprecated "`has_nav_bar? is deprecated. Use `nav_bar?`."
|
||||
nav_bar?
|
||||
end
|
||||
|
||||
|
||||
def nav_bar?
|
||||
!!self.navigation_controller
|
||||
end
|
||||
|
||||
def navigation_controller
|
||||
@navigation_controller ||= self.navigationController
|
||||
end
|
||||
@@ -45,7 +55,7 @@ module ProMotion
|
||||
|
||||
# [DEPRECATED]
|
||||
def load_view_controller
|
||||
warn "[DEPRECATION] `load_view_controller` is deprecated and doesn't actually do anything anymore. You can safely remove it from your code."
|
||||
PM.logger.deprecated "`load_view_controller` is deprecated and doesn't actually do anything anymore. You can safely remove it from your code."
|
||||
end
|
||||
|
||||
def set_tab_bar_item(args = {})
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
class TestDelegate < ProMotion::Delegate
|
||||
status_bar false
|
||||
|
||||
def on_load(app, options)
|
||||
end
|
||||
end
|
||||
|
||||
29
spec/unit/delegate_spec.rb
Normal file
29
spec/unit/delegate_spec.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
describe "PM::Delegate" do
|
||||
|
||||
before { @subject = TestDelegate.new }
|
||||
|
||||
it 'should call on_load on launch' do
|
||||
@subject.mock!(:on_load) do |app, options|
|
||||
options[:jamon].should.be.true
|
||||
app.should.be.kind_of(UIApplication)
|
||||
end
|
||||
|
||||
@subject.application(UIApplication.sharedApplication, didFinishLaunchingWithOptions:{jamon: true})
|
||||
end
|
||||
|
||||
it "should handle push notifications" do
|
||||
|
||||
@subject.mock!(:on_notification) do |notification|
|
||||
notification.should.be.kind_of(PM::PushNotification)
|
||||
notification.alert.should == "Eating Bacon"
|
||||
notification.badge.should == 42
|
||||
notification.sound.should == "jamon"
|
||||
@subject.aps_notification.should == notification
|
||||
end
|
||||
|
||||
launch_options = { UIApplicationLaunchOptionsRemoteNotificationKey => PM::PushNotification.fake_notification(alert: "Eating Bacon", badge: 42, sound: "jamon").notification }
|
||||
@subject.application(nil, didFinishLaunchingWithOptions:launch_options )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -116,9 +116,9 @@ describe "screen helpers" do
|
||||
|
||||
new_screen.parent_screen.should == @screen
|
||||
new_screen.title.should == 'Some Title'
|
||||
new_screen.is_modal?.should == true
|
||||
new_screen.modal?.should == true
|
||||
new_screen.hidesBottomBarWhenPushed.should == true
|
||||
new_screen.has_nav_bar?.should == true
|
||||
new_screen.nav_bar?.should == true
|
||||
end
|
||||
|
||||
it "should present the #main_controller when showing a modal screen" do
|
||||
|
||||
@@ -31,8 +31,8 @@ describe "screen properties" do
|
||||
HomeScreen.debug_mode.should == true
|
||||
end
|
||||
|
||||
it "#is_modal? should be true" do
|
||||
@screen.is_modal?.should == true
|
||||
it "#modal? should be true" do
|
||||
@screen.modal?.should == true
|
||||
end
|
||||
|
||||
it "should know it is the first screen" do
|
||||
@@ -115,7 +115,7 @@ describe "screen properties" do
|
||||
describe "navigation controller behavior" do
|
||||
|
||||
it "should have a nav bar" do
|
||||
@screen.has_nav_bar?.should == true
|
||||
@screen.nav_bar?.should == true
|
||||
end
|
||||
|
||||
it "#main_controller should return a navigation controller" do
|
||||
|
||||
Reference in New Issue
Block a user