Skip to content

Commit

Permalink
Merge f0e561c into 988fcb5
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan White committed Sep 23, 2018
2 parents 988fcb5 + f0e561c commit 5e5c081
Show file tree
Hide file tree
Showing 3 changed files with 296 additions and 0 deletions.
219 changes: 219 additions & 0 deletions lib/contacts_service.dart
@@ -1,7 +1,9 @@
import 'dart:async';
import 'dart:typed_data';

import 'package:collection/collection.dart';
import 'package:flutter/services.dart';
import 'package:meta/meta.dart';

class ContactsService {
static const MethodChannel _channel =
Expand Down Expand Up @@ -97,6 +99,221 @@ class Contact {
"avatar": contact.avatar
};
}

Map toMap() {
return Contact._toMap(this);
}

/// Updates this [Contact] with data from [contact].
void mergeWith(Contact contact) {}

/// "Adding" two contacts together is basically applying the data
/// from the missing field.
/// If you would like to merge the contacts, use the [merge] function.
operator +(Contact contact) =>
Contact(
givenName: this.givenName ?? contact.givenName,
middleName: this.middleName ?? contact.middleName,
prefix: this.prefix ?? contact.prefix,
suffix: this.suffix ?? contact.suffix,
familyName: this.familyName ?? contact.familyName,
company: this.company ?? contact.company,
jobTitle: this.jobTitle ?? contact.jobTitle,
emails: this.emails == null
? contact.emails
: Iterable.castFrom(
this.emails.toSet().union(contact.emails.toSet())),
phones: this.phones == null
? contact.phones
: Iterable.castFrom(
this.phones.toSet().union(contact.phones.toSet())),
postalAddresses: this.postalAddresses == null
? contact.postalAddresses
: Iterable.castFrom(this
.postalAddresses
.toSet()
.union(contact.postalAddresses.toSet())),
avatar: this.avatar ?? contact.avatar);

/// Returns true if all items in this contact are identical.
@override
bool operator ==(other) {
if (other is! Contact) return false;

Map otherMap = (other as Contact).toMap(); // ignore: test_types_in_equals
Map thisMap = this.toMap();

for (var key in otherMap.keys) {
if (otherMap[key] is! Iterable) {
if (thisMap[key] != otherMap[key]) {
return false;
}
} else if (otherMap[key] is Iterable) {
var equal = DeepCollectionEquality.unordered()
.equals(thisMap[key], otherMap[key]);
if (!equal) {
return false;
}
}
}
return true;
}

@override
int get hashCode {
return this.hashCode;
}

@override
String toString() {
// TODO: implement toString
return super.toString();
}
}

class RawContact {
final int rawContactId;
final int accountId;
int sourceid;
var rawContactIsReadOnly;
var version;
var dirty;
var deleted;
var contactId;
var aggregationMode;
var aggregationNeeded;
var customRingtone;
var sendToVoicemail;
var timesContacted;
var lastTimeContacted;
var starred;
var pinned;
var displayName;
var displayNameAlt;
var displayNameSource;
var phoneticName;
var phoneticNameStyle;
var sortKey;
var phonebookLabel;
var phonebookBucket;
var sortKeyAlt;
var phonebookLabelAlt;
var phonebookBucketAlt;
var nameVerified;
var sync1;
var sync2;
var sync3;
var sync4;
var syncUid;
var syncVersion;
var hasCalendarEvent;
var modifiedTime;
var isRestricted;
var ypSource;
var methodSelected;
var customVibrationType;
var customRingtonePath;
var messageNotification;
var messageNotificationPath;
var costSave;
var customLedType;
var backupId;

RawContact({@required this.rawContactId,
@required this.accountId,
this.sourceid,
this.rawContactIsReadOnly,
this.version,
this.dirty,
this.deleted,
this.contactId,
this.aggregationMode,
this.aggregationNeeded,
this.customRingtone,
this.sendToVoicemail,
this.timesContacted,
this.lastTimeContacted,
this.starred,
this.pinned,
this.displayName,
this.displayNameAlt,
this.displayNameSource,
this.phoneticName,
this.phoneticNameStyle,
this.sortKey,
this.phonebookLabel,
this.phonebookBucket,
this.sortKeyAlt,
this.phonebookLabelAlt,
this.phonebookBucketAlt,
this.nameVerified,
this.sync1,
this.sync2,
this.sync3,
this.sync4,
this.syncUid,
this.syncVersion,
this.hasCalendarEvent,
this.modifiedTime,
this.isRestricted,
this.ypSource,
this.methodSelected,
this.customVibrationType,
this.customRingtonePath,
this.messageNotification,
this.messageNotificationPath,
this.costSave,
this.customLedType,
this.backupId});

RawContact.fromMap(Map map)
: rawContactId = map['_id'],
this.accountId = map['account_id'] {
this.sourceid = map['sourceid'];
this.rawContactIsReadOnly = map['raw_contact_is_read_only'];
this.version = map['version'];
this.dirty = map['dirty'];
this.deleted = map['deleted'];
this.contactId = map['contact_id'];
this.aggregationMode = map['aggregation_mode'];
this.aggregationNeeded = map['aggregation_needed'];
this.customRingtone = map['custom_ringtone'];
this.sendToVoicemail = map['send_to_voicemail'];
this.timesContacted = map['times_contacted'];
this.lastTimeContacted = map['last_time_contacted'];
this.starred = map['starred'];
this.pinned = map['pinned'];
this.displayName = map['display_name'];
this.displayNameAlt = map['display_name_alt'];
this.displayNameSource = map['display_name_source'];
this.phoneticName = map['phonetic_name'];
this.phoneticNameStyle = map['phonetic_name_style'];
this.sortKey = map['sort_key'];
this.phonebookLabel = map['phonebook_label'];
this.phonebookBucket = map['phonebook_bucket'];
this.sortKeyAlt = map['sort_key_alt'];
this.phonebookLabelAlt = map['phonebook_label_alt'];
this.phonebookBucketAlt = map['phonebook_bucket_alt'];
this.nameVerified = map['name_verified'];
this.sync1 = map['sync1'];
this.sync2 = map['sync2'];
this.sync3 = map['sync3'];
this.sync4 = map['sync4'];
this.syncUid = map['sync_uid'];
this.syncVersion = map['sync_version'];
this.hasCalendarEvent = map['has_calendar_event'];
this.modifiedTime = map['modified_time'];
this.isRestricted = map['is_restricted'];
this.ypSource = map['yp_source'];
this.methodSelected = map['method_selected'];
this.customVibrationType = map['custom_vibration_type'];
this.customRingtonePath = map['custom_ringtone_path'];
this.messageNotification = map['message_notification'];
this.messageNotificationPath = map['message_notification_path'];
this.costSave = map['cost_save'];
this.customLedType = map['custom_led_type'];
this.backupId = map['backup_id'];
}
}

class PostalAddress {
Expand All @@ -107,6 +324,7 @@ class PostalAddress {
this.postcode,
this.region,
this.country});

String label, street, city, postcode, region, country;

PostalAddress.fromMap(Map m) {
Expand All @@ -132,6 +350,7 @@ class PostalAddress {
/// a [value], such as emails and phone numbers
class Item {
Item({this.label, this.value});

String label, value;

Item.fromMap(Map m) {
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Expand Up @@ -10,6 +10,7 @@ environment:
dependencies:
flutter:
sdk: flutter
collection: ^1.14.11

flutter:
plugin:
Expand Down
76 changes: 76 additions & 0 deletions test/contacts_test.dart
Expand Up @@ -57,6 +57,82 @@ void main() {
));
expectMethodCall(log, 'deleteContact');
});

test('should show contacts are equal', () {
Contact contact1 =
Contact(givenName: "givenName", familyName: "familyName", emails: [
Item(label: "Home", value: "example@example.com"),
Item(label: "Work", value: "example2@example.com"),
]);
Contact contact2 =
Contact(givenName: "givenName", familyName: "familyName", emails: [
Item(label: "Work", value: "example2@example.com"),
Item(label: "Home", value: "example@example.com"),
]);
expect(contact1 == contact2, true);
});

test('should produce a valid merged contact', () {
Contact contact1 =
Contact(givenName: "givenName", familyName: "familyName", emails: [
Item(label: "Home", value: "home@example.com"),
Item(label: "Work", value: "work@example.com"),
]);
Contact contact2 = Contact(familyName: "familyName", phones: [
Item(label: "Mobile", value: "111-222-3344")
], emails: [
Item(label: "Mobile", value: "mobile@example.com"),
], postalAddresses: [
PostalAddress(
label: 'Home',
street: "1234 Middle-of Rd",
city: "Nowhere",
postcode: "12345",
region: null,
country: null)
]);
Contact mergedContact =
Contact(givenName: "givenName",
familyName: "familyName",
emails: [
Item(label: "Home", value: "home@example.com"),
Item(label: "Mobile", value: "mobile@example.com"),
Item(label: "Work", value: "work@example.com"),
],
phones: [
Item(label: "Mobile", value: "111-222-3344")
],
postalAddresses: [
PostalAddress(
label: 'Home',
street: "1234 Middle-of Rd",
city: "Nowhere",
postcode: "12345",
region: null,
country: null)
]);

expect(contact1 + contact2, mergedContact);
});

test('should provide a map of the contact', () {
Contact contact = Contact(givenName: "givenName", familyName: "familyName");
expect(contact.toMap(), {
"identifier": null,
"displayName": null,
"givenName": "givenName",
"middleName": null,
"familyName": "familyName",
"prefix": null,
"suffix": null,
"company": null,
"jobTitle": null,
"emails": [],
"phones": [],
"postalAddresses": [],
"avatar": null
});
});
}

void expectMethodCall(List<MethodCall> log, String methodName) {
Expand Down

0 comments on commit 5e5c081

Please sign in to comment.