motion-addressbook 1.7.0 → 1.7.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 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