Skip to content

Releases: vestrel00/contacts-android

v0.1.9 - Entity hierarchy restructure, bug fixes, and dependency updates

18 Dec 01:34
Compare
Choose a tag to compare

There are a lot of changes in this release that I have put a lot of hours into 😅 All of those hours are worth it, because this library is now so much better because of it 😁. I am very excited to share this new version of Contacts, Reborn to the community! Please take a look, try it out, and let me know what ya think ❤️

Depending on how extensively you have integrated this library into your app, you may be affected be several breaking changes. Don't worry! They are easy to fix and I'll guide you. Just read the Migration guide section at the bottom of this release notes and you will be okay 🤞

Bugfixes

  1. #129 Photo thumbnail data is unintentionally included in all query results
    • This might have been negatively affecting your app's performance so be sure to adopt this new release if your apps shows all contacts without pagination.
  2. #135 Inserting or updating an event date to a single digit month or single digit day of month results in duplicate events
  3. #130 RawContactRefresh, DataRawContact, and BlankRawContactToRawContact extensions could return incorrect RawContact
  4. #131 DataRefresh extensions could return incorrect data
  5. #109 DataRefresh extension function throws exception for subclasses of MutableCommonDataEntity

Improvements and breaking changes

  1. #113 Fix hierarchy of CommonDataEntity
  2. #123 Use sealed interfaces!
  3. #115 Create an interface for creating a mutable copy of immutable entities
  4. #128 Revamped Entity hierarchy!
  5. #117 Create interface for "new entities" for insert APIs and remove nullable ID properties
  6. #134 Restructured all entities to either be "Existing" or "New"

Please keep in mind that releases below v1.0.0 may contain breaking changes!!! Anything below the semantic version v1.0.0 are implicitly experimental/non-stable. Backwards compatibility and deprecations will not be exercised until after v1.0.0 (the first true production release version) in order to keep the library clean and easy to change 👍

Dependency updates

I don't think these dependency bumps will affect you but let me know if it does!

  1. #121 Upgrade Kotlin to 1.6.0 (requires a bunch of other upgrades)
  2. #122 Remove explicit dependency on the Kotlin stdlib

New Contributors!

We got some new people in the house! 😍

  • @DriblingTrex made their first contribution in #127
    • Unfortunately, the GitHub account is not showing up in the Contributors list because the commits are not linked to the GitHub account 😭
  • @lau1944 created a very important issue; #116. It posed very important questions about the API design. Thank you for raising questions and even making suggestions. Because of you, this release contained a bunch of API improvements. Hence, the title of this release "Entity hierarchy restructure" 🔥
    • I still consider you a contributor even if you did not add code! Maybe, I should install the all-contributors bot; https://allcontributors.org...

Full Changelog

0.1.8...0.1.9

Want to discuss this release?

Head on over to the v0.1.9 Release Checklist and leave a comment!

Migration guide (from v0.1.8 to v0.1.9)

This should cover everything that could affect you. Let me know if I missed anything! If you don't care to look at the before-and-after, then go straight into the howto pages. I also made sure to update all documentation in code 😃

I. Entity and interfaces or abstract classes that inherit from it are now sealed except for custom data.

This means that you are no longer able to define your own entities, except for inheritors of CustomDataEntity.

II. Mutable entities have been split to either be "existing" or "new".

Previously, a mutable entity could represent both an "existing" entity (already inserted into the database and has non-null ID property values) or a "new" entity (not yet inserted into the database and has null ID property values). For example,

val mutableRawContact: MutableRawContact
val mutableEmail: MutableEmail

Now, a mutable entity can only represent either an "existing" or "new" entity...

val existingMutableRawContact: MutableRawContact
val existingMutableEmail: MutableEmail

val newMutableRawContact: NewRawContact
val newMutableEmail: NewEmail

The rest of the migration guide is directly related to this change.

III. Existing entities now have non-null ID properties.

You no longer have to worry about ID properties being null for existing entities.

Previously...

Contact {
    val id: Long?
}
RawContact {
    val id: Long?
    val contactId: Long?
}
Email {
    val id: Long?
    val rawContactId: Long?
    val contactId: Long?
}

Now...

Contact {
    val id: Long
}
RawContact {
    val id: Long
    val contactId: Long
}
Email {
    val id: Long
    val rawContactId: Long
    val contactId: Long
}

"New" entities do not have ID properties at all as they have not yet been inserted into the database.

IV. Getting instances of mutable entities have changed.

Previously...

val contact: Contact
val email: Email

val mutableContact: MutableContact = contact.toMutableContact()
val mutableEmail: MutableEmail = email.toMutableEmail()

Now...

val mutableContact: MutableContact = contact.mutableCopy()
val mutableEmail: MutableEmail = email.mutableCopy()

The toMutableXXX functions have been replaced with a generic mutableCopy function that is implemented by all inheritors of ImmutableEntityWithMutableType. I also added some more syntactic sugar for Kotlin users!

val mutableEmail = email.mutableCopy {
    address = "vestrel00@gmail.com"
}

Furthermore, you are no longer able to construct instances of existing mutable entities via constructors. This is done to ensure that existing entities can only come from the library APIs.

Yes, I am aware that data class provides a copy function that you can use to hack around this but I strongly discourage that. Read the "Creating Entities & data class" in the DEV_NOTES.md if you want to learn more about this.

V. Update and delete APIs now only accept existing entities.

This makes more sense now doesn't it? You can only update or delete something that already exists in the database.

✅ This will still work...

val existingMutableRawContact: MutableRawContact
Contacts(context).update().rawContacts(existingMutableRawContact).commit()
Contacts(context).delete().rawContacts(existingMutableRawContact).commit()

❌ This will not work (compile-time error)...

val newMutableRawContact: NewRawContact
Contacts(context).update().rawContacts(newMutableRawContact).commit()
Contacts(context).delete().rawContacts(newMutableRawContact).commit()

This applies to all update and delete APIs such as Update, ProfileUpdate, DataUpdate, GroupsUpdate, Delete, ProfileDelete, DataDelete, GroupsDelete,...

VI. Insert APIs now only accept new entities.

Inserting already "existing"/inserted entities doesn't really make sense. The only thing that will happen is that a duplicate will be created, which may or may not be what you intend to do.

❌ Anyways, this will no longer work (compile-time error)...

val existingMutableRawContact: MutableRawContact
Contacts(context).insert().rawContacts(existingMutableRawContact).commit()

✅ This will work...

val newMutableRawContact: NewRawContact
Contacts(context).insert().rawContacts(newMutableRawContact).commit()

This applies to all insert APIs such as Insert, ProfileInsert, GroupsInsert,...

VII. Extension functions in the util package are now only usable for existing entities.

Extension functions in the util package typically only work for existing entities (already inserted into the database- non-null ID property values). Prior to this release, those extension functions were also usable by "new" entities (not inserted into the database- null ID property values).

This led to consumers making incorrect, but valid assumptions. For example, in #116 Set photo did not save to system file, the consumer thought that this insert call would also set the photo...

Contacts(context)
            .insert()
            .rawContact {
                ...
                setPhoto(context, photoBitmap)
            }
            .commit()

It would make a lot of sense if it did. This should actually work and it will be supported in #119.

However, the above code does not actually set the photo because the RawContact in scope of the rawContact block has not yet been inserted, which means it does not have a non-null ID property value. So, setPhoto does nothing and fails.

Now, the setPhoto util extension function is only usable for existing Contacts or RawContacts. It will not accept new entities. The above code will not even compile! This avoids a lot of confusion 😁

v0.1.8 - Bug fixes, optimizations, minor API changes, Java support enhancements, and tons more documentation!

26 Nov 22:45
Compare
Choose a tag to compare

This release contains bug fixes, optimizations, API changes (for a cleaner API), and Java support enhancements. All of these things were discovered while writing Howto pages ❤️

Bug Fixes

  1. #108 The GroupsUpdate API no longer allows groups in the same Account to have duplicate titles.
    • This is the same behavior as the GroupsInsert API.

Optimizations

  1. Internally, the GroupsInsert API now only retrieves groups for Accounts that are related to the groups being inserted.
    • This is a minor performance improvement, but an improvement nonetheless!

Non-breaking API Changes

  1. Exposed the CustomDataRegistry.allFields() function to consumers.
    • This allows consumers to include all integrated custom fields in one call explicitly in query, insert, and update APIs.

Breaking API Changes

  1. The Accounts API is now accessible via the Contacts API.
    • Previously, to access the Accounts API, Accounts(context).
    • Now, to access the Accounts API, Contacts(context).accounts().
    • This streamlines all core APIs to be accessible via the Contacts API.
  2. The GlobalCustomDataRegistry has been removed.
    • The same has been applied to handle name and gender custom data modules.
    • This streamlines custom data integration to use only one instance of CustomDataRegistry per instance of Contacts.
    • This also makes things less error-prone.
  3. All extension functions in the contacts.core.util package and the corresponding functions in the async module now take a reference to the Contacts API instance instead of Context and CustomDataRegistry.
    • The same has been applied to handle name and gender custom data modules.
    • This streamlines all extension functions to use a reference to the Contacts instead of separate references to a Context and a CustomDataRegistry. Less arguments, the better!
    • This also makes things less error-prone.

Please keep in mind that releases below v1.0.0 may contain breaking changes!!! Anything below the semantic version v1.0.0 are implicitly experimental/non-stable. Backwards compatibility and deprecations will not be exercised until after v1.0.0 (the first true production release version) in order to keep the library clean and easy to change 😁

Java support enhancements

  1. Added @JvmStatic fun all() and @JvmStatic fun forMatching() for all object FieldSet to give Java users first-class access to all and forMatching properties in a similar way as Kotlin users.
    • The same has been applied to handle name and gender custom data modules.

Documentation

  1. Cleaned up some in-code KDocs.
  2. Wrote up a bunch more howto pages.

New Contributors!

I'm excited to have the very first (other than @vestrel00) contributor to this will-be-legendary library!!! 🔥🔥🔥🔥

FYI ❤️

You may have noticed that most of the above changes do not have a corresponding issue, which would have provided a lot more context and a paper trail to the related code changes. I need to keep in mind that this is now an open source project. Other people are looking at my work now, and perhaps even consuming it!

Therefore, in order to uphold some form of professionalism, all changes in future releases will have issues! It will also help in creating these release notes with the "Auto-generate release notes" button.

Full Changelog

0.1.7...0.1.8

v0.1.7 - Revamped include functions!

29 Oct 01:27
Compare
Choose a tag to compare

This release is full of big API improvements!

  1. Fixed queries inadvertently including unspecified fields.
    • Previously, some fields were being inadvertently included in query results due to the generic column names set by the ContactsContract. That is no longer the case!
  2. Added include functions to insert and update APIs.
    • Similar to query APIs, insert and update APIs now provide an includes function that allows you to specify which fields should be a part of the insert or update operation. All other fields are ignored.
  3. Added Contact.hasPhoneNumber field and wrote up documentation about matching contacts with no particular kind of data.

More info in How do I include only the data that I want?.

Full Changelog: 0.1.6...0.1.7

v0.1.6 - Events are now able to handle no-year dates!

16 Oct 01:19
Compare
Choose a tag to compare

Fixed Event date not handling no-year, minor code prettification, and wrote up several howto pages.

  • Fixed Event.date not handling no-year option.
  • MutableCommonDataEntity implementations are now using property delegate for primaryValue.
  • Wrote up howto pages for basic and advanced queries and others.

v0.1.5 - Added groupMemberships aggregation extension functions!

11 Oct 09:30
Compare
Choose a tag to compare

Added groupMemberships aggregation extension function in ContactData.

The groupMemberships aggregation extension functions were previously commented out because it may be unsafe for consumers to use as it may cause confusion to those unfamiliar with how Groups and GroupMemberships worked.

However, having these extensions may prove to be useful when showing group memberships of multiple raw contacts to matching Groups from different accounts.

a lot of documentation in the extension function is provided to minimize risk of misuse and confusion =)

v0.1.4 - Photo and thumbnail Uris are now exposed in ContactsEntity!

11 Oct 09:19
Compare
Choose a tag to compare

Exposed photoUri and photoThumbnailUri in ContactsEntity.

The photoUri and photoThumbnailUri in ContactsEntity we’re previously commented out to force users to use the ContactPhoto extensions. However, it has now been uncommented as it may be useful for showing contact photos in a list/recycler view…

v0.1.3 - Java consumer lint warnings fixed!

11 Oct 09:15
Compare
Choose a tag to compare

Fixed query order by functions causing lint warnings for Java consumers.

Fixes lint raising an issue for API query functions of the form fun x(vararg y: Type)

The fix was to add the @SafeVarargs function annotation

v0.1.2 - Jitpack distribution fixed!

11 Oct 09:12
Compare
Choose a tag to compare

Fixed Jitpack artifacts not being generated.

The previous release was not generating the artifacts when publishing to maven….

It’s fixed now though =)

v0.1.1 - Java version lowered to 7!

11 Oct 09:02
Compare
Choose a tag to compare

Java version is now back to 7 and lots more documentation

The Java version was previously set (recently) to Java 8 for no reason. This release reverts that change. Java version is now back to 7!

Plus some more documentation!

v0.1.0 - The open sourcing of Contacts, Reborn!

11 Oct 09:00
Compare
Choose a tag to compare

Ready for public alpha development .

Most, if not all, v1 functions have been implemented and manually tested by me.

0.1.x will be focused on making sure everything is documented. This includes writing howto guides for everything!