motion-addressbook 1.7.0 → 1.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 062e2ed0b9018682964f43fcaf0711c7c9147cc6
4
- data.tar.gz: ac3392b93c651c531dd6f506ffc9e6d5c1f272fb
3
+ metadata.gz: 686d48dc6904f9b9a55304536a80a6a54ba98609
4
+ data.tar.gz: a8c743b34dc3ec02f54d5bcc80110eba64b698bf
5
5
  SHA512:
6
- metadata.gz: fe803b3bf9eeae54d44b33ce8bd8f1c9016ca5ce62ba36c47a15da3b2fa0a09cca2141e7314c10b756a0a42afa0fbd9b64df8cf5b3b523963858de94721ef85a
7
- data.tar.gz: 0e3dd574fd3eb184f6408843613315816095cb69f4653465d056f29d0c8ae2d128c03eb782fbfe516d7eb9b4f616fc270971927914d61df16e6b942d362980ec
6
+ metadata.gz: 5b62d28e2ac4e801430d98ebb9dcd77f48dd4ce193d6966eb668ae6fa25effa893b3eba5c3c33db4da5b2fde48eabc24d22ce9f92507a5cc9c55a0567b3c6d66
7
+ data.tar.gz: 028c26080e06d2da83637864311c1130ea4b0399e378df4eb724b60c3097a061ecea3ba4bc2620338fe19ca652d682f73545c447254ab88bdf99204c7057faa4
data/.gitignore CHANGED
@@ -1,4 +1,4 @@
1
- .repl_history
1
+ .*history
2
2
  build
3
3
  resources/*.nib
4
4
  resources/*.momd
data/README.md CHANGED
@@ -86,16 +86,16 @@ end
86
86
  The iOS6 simulator does not demand AddressBook authorization. The iOS7
87
87
  simulator does.
88
88
 
89
- ### Showing the ABPeoplePicker
89
+ ### Showing the ABPeoplePickerNavigationController
90
90
 
91
91
  ```ruby
92
- AddressBook.pick { |person|
92
+ AddressBook.pick do |person|
93
93
  if person
94
94
  # person is an AddressBook::Person object
95
95
  else
96
96
  # canceled
97
97
  end
98
- }
98
+ end
99
99
  ```
100
100
 
101
101
  You can also specify the presenting controller:
@@ -106,6 +106,18 @@ AddressBook.pick presenter: self do |person|
106
106
  end
107
107
  ```
108
108
 
109
+ ### Showing the ABNewPersonViewController
110
+
111
+ ```ruby
112
+ AddressBook.create do |person|
113
+ if person
114
+ # person is an AddressBook::Person object
115
+ else
116
+ # canceled
117
+ end
118
+ end
119
+ ```
120
+
109
121
  ### Working with Person objects
110
122
 
111
123
  Get a list of existing people from the Address Book. On IOS, results
data/Rakefile CHANGED
@@ -1,17 +1,16 @@
1
1
  require "bundler/gem_tasks"
2
2
  $:.unshift("/Library/RubyMotion/lib")
3
+
3
4
  if ENV['osx']
4
5
  require 'motion/project/template/osx'
5
6
  else
6
7
  require 'motion/project/template/ios'
7
8
  end
9
+
8
10
  Bundler.setup
9
11
  Bundler.require
10
12
 
11
- unless ENV['osx']
12
- # iOS needs an AppDelegate for REPL to launch; steal one from BW
13
- require 'bubble-wrap/test'
14
- end
13
+ require 'bubble-wrap/reactor'
15
14
 
16
15
  Motion::Project::App.setup do |app|
17
16
  # Use `rake config' to see complete project settings.
@@ -22,4 +21,47 @@ Motion::Project::App.setup do |app|
22
21
  else
23
22
  app.specs_dir = "./spec/ios"
24
23
  end
24
+
25
+ if ENV['osx']
26
+ app.info_plist['LSUIElement'] = true
27
+ end
28
+ end
29
+
30
+ # The test suite may interfere with contacts already created in the
31
+ # simulator. In order to avoid disrupting anything the existing
32
+ # simulator environment, run the test suite in its own blank simulator
33
+ # and clean up afterwards.
34
+
35
+ namespace :spec do
36
+ task :isolate do
37
+ system "launchctl list | grep simulator | cut -f3 | xargs -L 1 launchctl remove"
38
+
39
+ @_protected = []
40
+ Dir.glob("#{ENV['HOME']}/Library/Application Support/iPhone Simulator/[0-9]*").each do |dir|
41
+ if Dir.exists?("#{dir}.backup")
42
+ warn "*" * 70
43
+ warn "PREVIOUS TEST RUN FAILED. RESTORING SIMULATOR BACKUP AND ABORTING."
44
+ warn "*" * 70
45
+ system "rm -rf \"#{dir}\""
46
+ File.rename("#{dir}.backup", dir)
47
+ exit 1
48
+ else
49
+ warn "PROTECTING EXISTING SIMULATOR IN #{dir}"
50
+ File.rename(dir, "#{dir}.backup")
51
+ @_protected << dir
52
+ end
53
+ end
54
+
55
+ at_exit do
56
+ system "launchctl list | grep simulator | cut -f3 | head -1 | xargs launchctl remove"
57
+
58
+ @_protected.each do |dir|
59
+ warn "RESTORING SIMULATOR IN #{dir}"
60
+ system "rm -rf \"#{dir}\""
61
+ File.rename("#{dir}.backup", dir)
62
+ end
63
+ end
64
+ end
65
+
66
+ task :simulator => :isolate
25
67
  end
@@ -0,0 +1,25 @@
1
+ class AppDelegate
2
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
3
+ @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
4
+ @window.rootViewController = UIViewController.alloc.init
5
+ @window.makeKeyAndVisible
6
+
7
+ command_line
8
+
9
+ true
10
+ end
11
+
12
+ def command_line
13
+ if command = NSProcessInfo.processInfo.environment['dump']
14
+ warn "Executing command line instruction: #{command}"
15
+ AddressBook::AddrBook.new do |ab|
16
+ case command
17
+ when 'people'
18
+ puts BW::JSON.generate(ab.people.map(&:attributes))
19
+ when 'groups'
20
+ puts BW::JSON.generate(ab.groups.map { |g| {name: g.name, members: g.members.map(&:uid) }})
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -28,6 +28,9 @@ BubbleWrap.require_ios do
28
28
  BW.require 'motion/address_book/ios/picker.rb' do
29
29
  file('motion/address_book/ios/picker.rb').uses_framework('AddressBookUI')
30
30
  end
31
+ BW.require 'motion/address_book/ios/creator.rb' do
32
+ file('motion/address_book/ios/creator.rb').uses_framework('AddressBookUI')
33
+ end
31
34
  end
32
35
 
33
36
  BubbleWrap.require_osx do
@@ -1,5 +1,5 @@
1
1
  module Motion
2
2
  module Addressbook
3
- VERSION = "1.7.0"
3
+ VERSION = "1.7.2"
4
4
  end
5
5
  end
@@ -15,6 +15,8 @@ module AddressBook
15
15
  if granted
16
16
  activate!
17
17
  block.call(self)
18
+ else
19
+ block.call(nil)
18
20
  end
19
21
  end
20
22
  else
@@ -25,6 +27,10 @@ module AddressBook
25
27
  end
26
28
  end
27
29
 
30
+ def self.instance
31
+ @instance ||= new
32
+ end
33
+
28
34
  def activate!
29
35
  @ab = LiveAddrBook.new(AddressBook.address_book)
30
36
  end
@@ -41,7 +47,7 @@ module AddressBook
41
47
  end
42
48
 
43
49
  def auth!
44
- raise "iOS Address Book authorization is required." if @ab.nil?
50
+ raise SecurityError, "iOS Address Book authorization is required." if @ab.nil?
45
51
  end
46
52
 
47
53
  def people(opts = {}, &block)
@@ -97,6 +103,14 @@ module AddressBook
97
103
  "#<#{self.class}:#{"0x%0x" % object_id} #{ab.status}>"
98
104
  end
99
105
 
106
+ def picker(options={}, &after)
107
+ AddressBook::Picker.show options.merge(ab: self), &after
108
+ end
109
+
110
+ def creator(options, &after)
111
+ AddressBook::Creator.show(options.merge(ab: self), &after)
112
+ end
113
+
100
114
  private
101
115
 
102
116
  def ab_people(opts = {})
@@ -0,0 +1,47 @@
1
+ module AddressBook
2
+ class Creator
3
+ class << self
4
+ attr_accessor :showing
5
+ end
6
+ def self.show(options={}, &after)
7
+ raise "Cannot show two Pickers" if showing?
8
+ @creator = self.new(options[:ab], &after)
9
+ @creator.show options
10
+ @creator
11
+ end
12
+
13
+ def self.showing?
14
+ !!showing
15
+ end
16
+
17
+ def initialize(ab, &after)
18
+ @ab = ab
19
+ @after = after
20
+ end
21
+
22
+ def show(options={})
23
+ self.class.showing = true
24
+
25
+ @new_person_ctlr = ABNewPersonViewController.alloc.init
26
+ @new_person_ctlr.newPersonViewDelegate = self
27
+
28
+ @presenter = options.fetch :presenter, UIApplication.sharedApplication.keyWindow.rootViewController
29
+ @animated = options.fetch :animated, true
30
+ @presenter.presentViewController(@new_person_ctlr, animated: @animated, completion: nil)
31
+ end
32
+
33
+ def hide(ab_person=nil)
34
+ person = ab_person && @ab.person(ABRecordGetRecordID(ab_person))
35
+
36
+ @presenter.dismissViewControllerAnimated(@animated, completion: lambda do
37
+ @after.call(person) if @after
38
+ self.class.showing = false
39
+ end)
40
+ end
41
+
42
+ def newPersonViewController(new_person_ctlr, didCompleteWithNewPerson: ab_person)
43
+ hide(ab_person)
44
+ end
45
+
46
+ end
47
+ end
@@ -60,19 +60,16 @@ module AddressBook
60
60
  @mv_type = multi_value_property_type
61
61
  mv = ABMultiValueCreateMutable(mv_type)
62
62
 
63
- case mv_type
64
- when KABMultiStringPropertyType
65
- @attributes.each do |rec|
66
- ABMultiValueAddValueAndLabel(mv, rec[:value], localized_label(rec[:label]), nil)
67
- end
68
- when KABMultiDateTimePropertyType
69
- @attributes.each do |rec|
70
- ABMultiValueAddValueAndLabel(mv, rec[:date], localized_label(rec[:label]), nil)
71
- end
72
- else # KABMultiDictionaryPropertyType
73
- @attributes.each do |rec|
63
+ @attributes.each do |rec|
64
+ label = localized_label(rec[:label])
65
+ case mv_type
66
+ when KABMultiStringPropertyType
67
+ ABMultiValueAddValueAndLabel(mv, rec[:value], label, nil)
68
+ when KABMultiDateTimePropertyType
69
+ ABMultiValueAddValueAndLabel(mv, rec[:date], label, nil)
70
+ else # KABMultiDictionaryPropertyType
74
71
  if value = dict_to_ab_record(rec)
75
- ABMultiValueAddValueAndLabel(mv, value, localized_label(rec[:label]), nil)
72
+ ABMultiValueAddValueAndLabel(mv, value, label, nil)
76
73
  end
77
74
  end
78
75
  end
@@ -10,7 +10,7 @@ module AddressBook
10
10
  end
11
11
 
12
12
  def self.all(options = {})
13
- AddressBook::AddrBook.new.people(options)
13
+ AddressBook::AddrBook.instance.people(options)
14
14
  end
15
15
 
16
16
  def self.create(attributes)
@@ -5,7 +5,7 @@ module AddressBook
5
5
  end
6
6
  def self.show(options={}, &after)
7
7
  raise "Cannot show two Pickers" if showing?
8
- @picker = Picker.new(&after)
8
+ @picker = self.new(options[:ab] || AddressBook::AddrBook.instance, &after)
9
9
  @picker.show options
10
10
  @picker
11
11
  end
@@ -14,7 +14,8 @@ module AddressBook
14
14
  !!showing
15
15
  end
16
16
 
17
- def initialize(&after)
17
+ def initialize(ab, &after)
18
+ @ab = ab
18
19
  @after = after
19
20
  end
20
21
 
@@ -23,17 +24,19 @@ module AddressBook
23
24
 
24
25
  @people_picker_ctlr = ABPeoplePickerNavigationController.alloc.init
25
26
  @people_picker_ctlr.peoplePickerDelegate = self
26
- presenter = options.fetch :presenter, UIApplication.sharedApplication.keyWindow.rootViewController
27
- presenter.presentViewController(@people_picker_ctlr, animated:true, completion:nil)
27
+
28
+ @presenter = options.fetch :presenter, UIApplication.sharedApplication.keyWindow.rootViewController
29
+ @animated = options.fetch :animated, true
30
+ @presenter.presentViewController(@people_picker_ctlr, animated: @animated, completion: nil)
28
31
  end
29
32
 
30
33
  def hide(ab_person=nil)
31
- person = ab_person ? AddressBook::Person.new({}, ab_person) : nil
34
+ person = ab_person && @ab.person(ABRecordGetRecordID(ab_person))
32
35
 
33
- UIApplication.sharedApplication.keyWindow.rootViewController.dismissViewControllerAnimated(true, completion:lambda{
34
- @after.call(person) if @after
35
- self.class.showing = false
36
- })
36
+ @presenter.dismissViewControllerAnimated(@animated, completion: lambda do
37
+ @after.call(person) if @after
38
+ self.class.showing = false
39
+ end)
37
40
  end
38
41
 
39
42
  def peoplePickerNavigationController(people_picker, shouldContinueAfterSelectingPerson:ab_person)
@@ -49,13 +52,6 @@ module AddressBook
49
52
  def peoplePickerNavigationControllerDidCancel(people_picker)
50
53
  hide
51
54
  end
52
- end
53
- end
54
55
 
55
- module AddressBook
56
- module_function
57
- def pick(options={}, &after)
58
- AddressBook::Picker.show options, &after
59
56
  end
60
57
  end
61
-
@@ -0,0 +1,33 @@
1
+ describe AddressBook::Creator do
2
+ before do
3
+ @ab = AddressBook::AddrBook.new
4
+ @person = @ab.create_person(first_name: 'Colin')
5
+ @ab_person = @person.ab_person
6
+ end
7
+
8
+ after do
9
+ @person.delete!
10
+ end
11
+
12
+ describe 'IOS UI for creating an entry' do
13
+ before do
14
+ @created_person = :not_set
15
+ @picker = @ab.creator(animated: false) do |person|
16
+ @created_person = person
17
+ end
18
+ end
19
+
20
+ it 'should yield the created person' do
21
+ @picker.newPersonViewController(nil, didCompleteWithNewPerson: @ab_person)
22
+ @created_person.should.not == nil
23
+ @created_person.should.be.kind_of?(AddressBook::Person)
24
+ @created_person.first_name.should == 'Colin'
25
+ end
26
+
27
+ it 'should yield nil if canceled' do
28
+ @created_person.should == :not_set
29
+ @picker.newPersonViewController(nil, didCompleteWithNewPerson: nil)
30
+ @created_person.should == nil
31
+ end
32
+ end
33
+ end
@@ -11,7 +11,7 @@ describe AddressBook::Person do
11
11
  describe 'new' do
12
12
  before do
13
13
  @data = new_alex
14
- @alex = AddressBook::Person.new(@data)
14
+ @alex = @ab.new_person(@data)
15
15
  end
16
16
  it 'should create but not save in the address book' do
17
17
  @alex.should.be.new_record
@@ -30,7 +30,7 @@ describe AddressBook::Person do
30
30
  describe 'existing' do
31
31
  before do
32
32
  @email = unique_email
33
- @alex = AddressBook::Person.create(new_alex(@email))
33
+ @alex = @ab.create_person(new_alex(@email))
34
34
  end
35
35
  after do
36
36
  @alex.delete!
@@ -93,16 +93,16 @@ describe AddressBook::Person do
93
93
 
94
94
  describe '.all' do
95
95
  it 'should have the person we created' do
96
- all_names = AddressBook::Person.all.map do |person|
96
+ all_names = @ab.people.map do |person|
97
97
  [person.first_name, person.last_name]
98
98
  end
99
99
  all_names.should.include? [@alex.first_name, @alex.last_name]
100
100
  end
101
101
 
102
102
  it 'should get bigger when we create another' do
103
- initial_people_count = AddressBook::Person.all.size
104
- @person = AddressBook::Person.create({:first_name => 'Alex2', :last_name=>'Rothenberg2'})
105
- AddressBook::Person.all.size.should.equal (initial_people_count + 1)
103
+ initial_people_count = @ab.count
104
+ @person = @ab.create_person({:first_name => 'Alex2', :last_name=>'Rothenberg2'})
105
+ @ab.count.should.equal (initial_people_count + 1)
106
106
  @person.delete!
107
107
  end
108
108
  end
@@ -111,7 +111,7 @@ describe AddressBook::Person do
111
111
  describe '.find_or_new_by_XXX - new or existing' do
112
112
  before do
113
113
  @email = unique_email
114
- @alex = AddressBook::Person.create(new_alex(@email))
114
+ @alex = @ab.create_person(new_alex(@email))
115
115
  end
116
116
  after do
117
117
  @alex.delete!
@@ -175,7 +175,7 @@ describe AddressBook::Person do
175
175
 
176
176
  describe 'a new person' do
177
177
  before do
178
- @ab_person = AddressBook::Person.new(@attributes)
178
+ @ab_person = @ab.new_person(@attributes)
179
179
  end
180
180
 
181
181
  it 'should not be existing' do
@@ -314,7 +314,7 @@ describe AddressBook::Person do
314
314
 
315
315
  describe 'an existing person' do
316
316
  before do
317
- @orig_ab_person = AddressBook::Person.new(@attributes)
317
+ @orig_ab_person = @ab.new_person(@attributes)
318
318
  @orig_ab_person.save
319
319
  @ab_person = AddressBook::Person.find_or_new_by_email(@attributes[:emails][0][:value])
320
320
  end
@@ -356,7 +356,7 @@ describe AddressBook::Person do
356
356
  { :label => 'work' },
357
357
  { :label => 'work', :url => 'http://state.edu/college' }
358
358
  ]
359
- @ab_person = AddressBook::Person.create(@attributes)
359
+ @ab_person = @ab.create_person(@attributes)
360
360
  end
361
361
  after do
362
362
  @ab_person.delete!
@@ -381,7 +381,7 @@ describe AddressBook::Person do
381
381
 
382
382
  describe "organization record" do
383
383
  before do
384
- @person = AddressBook::Person.new(
384
+ @person = @ab.new_person(
385
385
  :first_name => 'John',
386
386
  :last_name => 'Whorfin',
387
387
  :organization => 'Acme Inc.',
@@ -397,7 +397,7 @@ describe AddressBook::Person do
397
397
 
398
398
  describe 'method missing magic' do
399
399
  before do
400
- @person = AddressBook::Person.new
400
+ @person = @ab.new_person({})
401
401
  end
402
402
  describe 'getters' do
403
403
  it 'should have a getter for each attribute' do
@@ -466,36 +466,64 @@ describe AddressBook::Person do
466
466
 
467
467
  describe "sorting" do
468
468
  before do
469
+ # warn "BEFORE CREATION COUNT: #{@ab.count}"
469
470
  @ab.people.each(&:delete!)
470
471
 
471
- @p1 = @ab.create_person({:first_name => 'Bob', :last_name => 'Edwards'}).uid
472
- @p2 = @ab.create_person({:first_name => 'Doris', :last_name => 'Channing'}).uid
473
- @p3 = @ab.create_person({:first_name => 'Anne', :last_name => 'Brown'}).uid
474
- @p4 = @ab.create_person({:first_name => 'Eddie', :last_name => 'Anderson'}).uid
475
- @p5 = @ab.create_person({:first_name => 'Carol', :last_name => 'Dolittle'}).uid
472
+ @p1 = @ab.create_person(first_name: 'Bob', last_name: 'Edwards')
473
+ # warn "I CREATED #{@p1}"
474
+ @p2 = @ab.create_person(first_name: 'Doris', last_name: 'Channing')
475
+ @p3 = @ab.create_person(first_name: 'Anne', last_name: 'Brown')
476
+ @p4 = @ab.create_person(first_name: 'Eddie', last_name: 'Anderson')
477
+ @p5 = @ab.create_person(first_name: 'Carol', last_name: 'Dolittle')
478
+ # warn "AFTER CREATION COUNT: #{@ab.count}"
476
479
  end
477
480
 
478
- it "should sort on last name using OS sort" do
479
- @ab.people(ordering: KABPersonSortByLastName).map(&:uid).should.equal [@p4, @p3, @p2, @p5, @p1]
480
- end
481
- it "should support last-name sort in Person#all" do
482
- AddressBook::Person.all(ordering: KABPersonSortByLastName).map(&:uid).should.equal [@p4, @p3, @p2, @p5, @p1]
481
+ after do
482
+ # warn "BEFORE CLEANUP COUNT: #{@ab.count}"
483
+ @ab.people.each(&:delete!)
484
+ # warn "AFTER CLEANUP COUNT: #{@ab.count}"
485
+ # [@p1, @p2, @p3, @p4, @p5].each(&:delete!)
483
486
  end
484
487
 
485
- it "should sort on first name using OS sort" do
486
- @ab.people(ordering: KABPersonSortByFirstName).map(&:uid).should.equal [@p3, @p1, @p5, @p2, @p4]
487
- end
488
- it "should support first-name sort in Person#all" do
489
- AddressBook::Person.all(ordering: KABPersonSortByFirstName).map(&:uid).should.equal [@p3, @p1, @p5, @p2, @p4]
490
- end
488
+ describe "with different sort orders" do
489
+ it "should sort on last name using OS sort" do
490
+ # warn "PEOPLE COUNT IS #{@ab.people.count}"
491
+ expectation = [@p4, @p3, @p2, @p5, @p1].map(&:uid)
492
+ @ab.people(ordering: KABPersonSortByLastName).map(&:uid).should.equal expectation
493
+ end
494
+ # it "should support last-name sort in Person#all" do
495
+ # AddressBook::Person.all(ordering: KABPersonSortByLastName).map(&:uid).should.equal [@p4, @p3, @p2, @p5, @p1]
496
+ # end
497
+
498
+ it "should pass" do
499
+ 3.should == 3
500
+ end
501
+
502
+ it "should sort on first name using OS sort" do
503
+ # warn "PEOPLE COUNT IS #{@ab.people.count}"
504
+ expectation = [@p3, @p1, @p5, @p2, @p4].map(&:uid)
505
+ @ab.people(ordering: KABPersonSortByFirstName).map(&:uid).should.equal expectation
506
+ end
507
+ # it "should support first-name sort in Person#all" do
508
+ # AddressBook::Person.all(ordering: KABPersonSortByFirstName).map(&:uid).should.equal [@p3, @p1, @p5, @p2, @p4]
509
+ # end
491
510
 
492
- it "should support a custom sort order" do
493
- ordered = @ab.people { |p| p.last_name[1] }.map(&:uid)
494
- ordered.should.equal [@p1, @p2, @p4, @p5, @p3]
511
+ it "should pass" do
512
+ 3.should == 3
513
+ end
514
+
515
+ it "should support a custom sort order" do
516
+ # warn "@ab.people is #{@ab.people}"
517
+ # warn "PEOPLE COUNT IS #{@ab.people.count}"
518
+ ordered = @ab.people { |p| p.last_name[1] }.map(&:uid)
519
+ # warn "sorted is #{ordered}"
520
+ expectation = [@p1, @p2, @p4, @p5, @p3].map(&:uid)
521
+ ordered.should.equal expectation
522
+ end
495
523
  end
496
524
  end
497
525
 
498
- describe "notifications" do
526
+ describe "notifications across AB instances" do
499
527
  before do
500
528
  @ab1 = AddressBook::AddrBook.new
501
529
  @ab2 = AddressBook::AddrBook.new
@@ -505,15 +533,26 @@ describe AddressBook::Person do
505
533
  App.notification_center.observe :addressbook_updated do |notification|
506
534
  @notifications += 1
507
535
  end
536
+ end
508
537
 
538
+ # should see a single notification for each change to the AB database:
539
+ # 2 creations, 2 deletions
540
+ it "should come in once for every external change" do
509
541
  @alice = @ab2.create_person({first_name: 'Alice'})
510
542
  @bob = @ab1.create_person({first_name: 'Bob'})
511
543
  @alice.delete!
512
544
  @bob.delete!
513
- end
514
545
 
515
- it "should be notified of every change" do
516
546
  @notifications.should.equal 4
517
547
  end
518
548
  end
549
+
550
+ after do
551
+ puts
552
+ NSLog("=============== person_spec.rb line #{__LINE__} ===============")
553
+ wait 1 do
554
+ NSLog("=============== person_spec.rb line #{__LINE__} ===============")
555
+ end
556
+ end
557
+
519
558
  end
@@ -1,34 +1,36 @@
1
- # I don't know how to test a class wrapping a controller like this yet
2
- #
3
- # describe AddressBook::Picker do
4
- # describe 'IOS UI for finding people' do
5
- # before do
6
- # @selected_person = nil
7
- # @picker = AddressBook.pick do |person|
8
- # @selected_person = person
9
- # end
10
- # end
1
+ describe AddressBook::Picker do
2
+ describe 'IOS UI for finding people' do
3
+ before do
4
+ @ab = AddressBook::AddrBook.new
5
+ @colin = @ab.create_person(first_name: 'Colin')
6
+ @ab_person = @colin.ab_person
7
+ @selected_person = nil
8
+ @picker = @ab.picker(animated: false) do |person|
9
+ @selected_person = person
10
+ end
11
+ end
11
12
 
12
- # it 'should yield the selected person' do
13
- # ab_person = AddressBook::Person.new(first_name: 'Colin').ab_person
14
- # @picker.peoplePickerNavigationController(@picker_nav_controller, shouldContinueAfterSelectingPerson: ab_person)
15
- # @selected_person.should.not == nil
16
- # @selected_person.first_name.should == 'Colin'
17
- # end
13
+ after do
14
+ @colin.delete!
15
+ end
18
16
 
19
- # it 'should yield the selected person' do
20
- # property = :some_property
21
- # id = :some_id
22
- # ab_person = AddressBook::Person.new(first_name: 'Colin').ab_person
23
- # @picker.peoplePickerNavigationController(@picker_nav_controller, shouldContinueAfterSelectingPerson: ab_person, property:property, identifier:id)
24
- # @selected_person.should.not == nil
25
- # @selected_person.first_name.should == 'Colin'
26
- # end
17
+ it 'should yield the selected person' do
18
+ @picker.peoplePickerNavigationController(@picker_nav_controller, shouldContinueAfterSelectingPerson: @ab_person)
19
+ @selected_person.should.not == nil
20
+ @selected_person.first_name.should == 'Colin'
21
+ end
27
22
 
28
- # it 'should yield nil when cancelled' do
29
- # ab_person = AddressBook::Person.new(first_name: 'Colin').ab_person
30
- # @picker.peoplePickerNavigationControllerDidCancel(@picker_nav_controller)
31
- # @selected_person.should == nil
32
- # end
33
- # end
34
- # end
23
+ it 'should yield the selected person' do
24
+ property = :some_property
25
+ id = :some_id
26
+ @picker.peoplePickerNavigationController(@picker_nav_controller, shouldContinueAfterSelectingPerson: @ab_person, property:property, identifier:id)
27
+ @selected_person.should.not == nil
28
+ @selected_person.first_name.should == 'Colin'
29
+ end
30
+
31
+ it 'should yield nil when cancelled' do
32
+ @picker.peoplePickerNavigationControllerDidCancel(@picker_nav_controller)
33
+ @selected_person.should == nil
34
+ end
35
+ end
36
+ end
@@ -1,48 +1,27 @@
1
- # These methods are intended to protect contents of the simulator
2
- # instance from destruction when the spec suite runs. Specifically,
3
- # the contents of the iOS Address Book, which is global to all
4
- # applications.
5
- #
6
- # WARNING: Altering the simulator configuration at runtime is a risky
7
- # practice. If we use `Kernel.system` instead of backquotes when
8
- # invoking `mv` and `rm` below, the simulator throws a warning:
9
- #
10
- # The iOS Simulator libSystem was initialized out of order. This
11
- # is most often caused by running host executables or inserting
12
- # host dylibs. In the future, this will cause an abort.
13
- #
14
-
15
- SIMULATOR_ROOT = "#{ENV['HOME']}/../.."
16
- AB_PATH = SIMULATOR_ROOT + "/Library/AddressBook"
17
- AB_PATH_BAK = AB_PATH + ".bak"
18
-
19
- def protect_existing_address_book
20
- # Can't use ruby methods to operate on these directories because the
21
- # iOS layer protects them, but shelling out is still allowed so we
22
- # can alter the world that way.
23
-
24
- warn "PROTECTING EXISTING ADDRESS BOOK IN SIMULATOR"
25
-
26
- `rm -rf \"#{AB_PATH_BAK}\"`
27
- `mv \"#{AB_PATH}\" \"#{AB_PATH_BAK}\"`
28
- # Kernel.system "rm -rf \"#{AB_PATH_BAK}\""
29
- # Kernel.system "mv \"#{AB_PATH}\" \"#{AB_PATH_BAK}\""
30
- end
31
-
32
- at_exit do
33
- warn "RESTORING ORIGINAL ADDRESS BOOK IN SIMULATOR"
34
-
35
- Kernel.system "rm -rf \"#{AB_PATH}\""
36
- Kernel.system "mv \"#{AB_PATH_BAK}\" \"#{AB_PATH}\""
37
- end
38
-
39
- def wait_for_authorization
40
- @semaphore = Dispatch::Semaphore.new(0)
41
- AddressBook::AddrBook.new do
42
- @semaphore.signal
1
+ module Bacon
2
+ class << self
3
+ @@old_run = instance_method(:run)
4
+ @@already_started = false
5
+
6
+ def ab_connect
7
+ AddressBook::AddrBook.new do |ab|
8
+ if ab
9
+ EM.schedule_on_main do
10
+ Bacon.run
11
+ end
12
+ else
13
+ warn "ACCESS DENIED - ABORTING"
14
+ exit
15
+ end
16
+ end
17
+ end
18
+
19
+ def run
20
+ if AddressBook.authorized?
21
+ @@old_run.bind(self).call
22
+ else
23
+ ab_connect
24
+ end
25
+ end
43
26
  end
44
- @semaphore.wait
45
27
  end
46
-
47
- protect_existing_address_book
48
- wait_for_authorization
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion-addressbook
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 1.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Rothenberg
@@ -9,48 +9,48 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-12-02 00:00:00.000000000 Z
12
+ date: 2014-04-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bubble-wrap
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ~>
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
20
  version: '1.3'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ~>
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: '1.3'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rake
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - '>='
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
34
  version: '0'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - '>='
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rspec
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - '>='
46
+ - - ">="
47
47
  - !ruby/object:Gem::Version
48
48
  version: '0'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - '>='
53
+ - - ">="
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0'
56
56
  description: A RubyMotion wrapper around the iOS & OSX Address Book frameworks
@@ -61,19 +61,20 @@ executables: []
61
61
  extensions: []
62
62
  extra_rdoc_files: []
63
63
  files:
64
- - .gitignore
65
- - .travis.yml
64
+ - ".gitignore"
65
+ - ".travis.yml"
66
66
  - Gemfile
67
67
  - LICENSE
68
68
  - README.md
69
69
  - Rakefile
70
+ - app/app_delegate.rb
70
71
  - lib/motion-addressbook.rb
71
72
  - lib/motion-addressbook/version.rb
72
73
  - motion-addressbook.gemspec
73
74
  - motion/address_book.rb
74
75
  - motion/address_book/ios/addr_book.rb
76
+ - motion/address_book/ios/creator.rb
75
77
  - motion/address_book/ios/group.rb
76
- - motion/address_book/ios/multi_value.rb
77
78
  - motion/address_book/ios/multi_valued.rb
78
79
  - motion/address_book/ios/person.rb
79
80
  - motion/address_book/ios/picker.rb
@@ -82,6 +83,7 @@ files:
82
83
  - motion/address_book/osx/group.rb
83
84
  - motion/address_book/osx/multi_valued.rb
84
85
  - motion/address_book/osx/person.rb
86
+ - spec/ios/address_book/creator_spec.rb
85
87
  - spec/ios/address_book/group_spec.rb
86
88
  - spec/ios/address_book/multi_valued_spec.rb
87
89
  - spec/ios/address_book/person_spec.rb
@@ -104,21 +106,22 @@ require_paths:
104
106
  - lib
105
107
  required_ruby_version: !ruby/object:Gem::Requirement
106
108
  requirements:
107
- - - '>='
109
+ - - ">="
108
110
  - !ruby/object:Gem::Version
109
111
  version: '0'
110
112
  required_rubygems_version: !ruby/object:Gem::Requirement
111
113
  requirements:
112
- - - '>='
114
+ - - ">="
113
115
  - !ruby/object:Gem::Version
114
116
  version: '0'
115
117
  requirements: []
116
118
  rubyforge_project:
117
- rubygems_version: 2.1.11
119
+ rubygems_version: 2.2.2
118
120
  signing_key:
119
121
  specification_version: 4
120
122
  summary: A RubyMotion wrapper around the iOS & OSX Address Book frameworks
121
123
  test_files:
124
+ - spec/ios/address_book/creator_spec.rb
122
125
  - spec/ios/address_book/group_spec.rb
123
126
  - spec/ios/address_book/multi_valued_spec.rb
124
127
  - spec/ios/address_book/person_spec.rb
@@ -1,120 +0,0 @@
1
- module AddressBook
2
- class MultiValue
3
- attr_reader :attributes, :ab_multi_values
4
-
5
- def self.attribute_map
6
- { :mobile => KABPersonPhoneMobileLabel ,
7
- :iphone => KABPersonPhoneIPhoneLabel ,
8
- :main => KABPersonPhoneMainLabel ,
9
- :home_fax => KABPersonPhoneHomeFAXLabel,
10
- :work_fax => KABPersonPhoneWorkFAXLabel,
11
- :pager => KABPersonPhonePagerLabel ,
12
- :work => KABWorkLabel ,
13
- :home => KABHomeLabel ,
14
- :other => KABOtherLabel
15
- }
16
- end
17
- def attribute_map
18
- self.class.attribute_map
19
- end
20
-
21
- def alex
22
- ABMultiValueGetIdentifierAtIndex @ab_multi_values, 0
23
- end
24
-
25
- def initialize(attributes={}, existing_ab_multi_values=nil)
26
- @attributes = {}
27
- if existing_ab_multi_values
28
- @ab_multi_values = ABMultiValueCreateMutableCopy(existing_ab_multi_values)
29
- load_attributes_from_ab
30
- else
31
- @ab_multi_values = ABMultiValueCreateMutable(KABMultiStringPropertyType)
32
- end
33
- attributes.each do |attribute, value|
34
- send("#{attribute}=", value)
35
- end
36
- end
37
-
38
- def method_missing(name, *args)
39
- if attribute_name = getter?(name)
40
- get(attribute_name)
41
- elsif attribute_name = setter?(name)
42
- set(attribute_name, args.first)
43
- else
44
- super
45
- end
46
- end
47
-
48
- def self.is_attribute?(attribute_name)
49
- return false if attribute_name.nil?
50
- attribute_map.include?(attribute_name.to_sym) || [:email, :phone_number].include?( attribute_name.to_sym)
51
- end
52
-
53
- def getter?(method_name)
54
- if self.class.is_attribute? method_name
55
- method_name
56
- else
57
- nil
58
- end
59
- end
60
- def setter?(method_name)
61
- method_name.to_s =~ /^(\w*)=$/
62
- if self.class.is_attribute? $1
63
- $1
64
- else
65
- nil
66
- end
67
- end
68
-
69
- def get(attribute_name)
70
- attributes[attribute_name.to_sym] ||= get_field(attribute_map[attribute_name])
71
- end
72
-
73
- def set(attribute_name, value)
74
- set_field(attribute_map[attribute_name.to_sym], value)
75
- attributes[attribute_name.to_sym] = value
76
- end
77
-
78
- def set_field(ab_label, value)
79
- if blank?(ab_label)
80
- ABMultiValueAddValueAndLabel(@ab_multi_values, value, ab_label, nil) unless value.nil?
81
- else
82
- ABMultiValueReplaceValueAtIndex(@ab_multi_values, value, 0)
83
- end
84
- end
85
-
86
- def get_field(ab_label)
87
- puts
88
- puts [__FILE__, __LINE__, ab_label].inspect
89
- index = ABMultiValueGetIndexForIdentifier(@ab_multi_values, ab_label)
90
- puts [__FILE__, __LINE__, index].inspect
91
- ABMultiValueCopyValueAtIndex(@ab_multi_values, index)
92
- end
93
-
94
- def values
95
- attributes.values
96
- end
97
-
98
- def include? value
99
- return false if values.nil?
100
- values.include? value
101
- end
102
-
103
- def size
104
- ABMultiValueGetCount(@ab_multi_values)
105
- end
106
-
107
- def load_attributes_from_ab
108
- (0...size).to_a.each do |i|
109
- label = ABMultiValueCopyLabelAtIndex(@ab_multi_values, i)
110
- @attributes[attribute_map.invert[label]] = ABMultiValueCopyValueAtIndex(@ab_multi_values, i)
111
- end
112
- end
113
-
114
- private
115
- def blank?(ab_label)
116
- attributes[ab_label].nil?
117
- end
118
-
119
- end
120
- end