at_contact

pub package pub points gitHub license

Overview

The at_contact package is for Flutter developers who would like to persist contacts in their @platform application. The at_contact library provides features to add, update, and delete contacts on the @platform.

This open source package is written in Dart, supports Flutter and follows the @‎platform's decentralized, edge computing model with the following features:

  • Cryptographic control of data access through personal data stores
  • No application backend needed
  • End to end encryption where only the data owner has the keys
  • Private and surveillance free connectivity

We call giving people control of access to their data “flipping the internet” and you can learn more about how it works by reading this overview.

Get started

There are three options to get started using this package.

1. Clone it from GitHub

Feel free to fork a copy of the source from the GitHub repo.

$ git clone https://github.com/YOUR-USERNAME/YOUR-REPOSITORY

2. Manually add the package to a project

Instructions on how to manually add this package to you project can be found on pub.dev here.

How it works

Setup

$ dart pub add at_contact

Usage

  • Create an instance of AtContactsImpl, We make use of AtClientManager for AtClient to be passed.
// Create an instance of AtClient.
AtClient atClientInstance = AtClientManager.getInstance().atClient;

// Create an instance of AtContactsImpl.
// It takes 2 positional arguments called AtClient and atSign.
// One optional argument called regexType.
AtContactsImpl _atContact = AtContactsImpl(atClientInstance, atClientInstance.getCurrentAtSign());

Contacts

  • If the user wants to add a contact, call add() function from the _atContact instance. Provide the contact details to add() function.

Future<void> _addContact() async {
    // Pass the user input data to respective fields of AtContact.
    AtContact contact = AtContact()
    // Pass the user atSign here
    ..atSign = atSign
    ..createdOn = DateTime.now()
    // Pass this value if you want to make the contact your favourite.
    ..favourite = _isFavouriteSelected
    // Contact type can be - Individual / Institute / Other
    ..type = ContactType.Individual;
    bool isContactAdded = await _atContact.add(contact);
    print(isContactAdded ? 'Contact added successfully' : 'Failed to add contact');
}
  • If user wants to get the data of a contact, call get() function by passing the user's atSign as the positional argument.
AtContact? userContact;

@override
Future<void> _getContactDetails() async {
    // Optionally pass the atKeys.
    AtContact? _contact = await _atContact.get(atSign);
    if(_contact == null){
        print("Failed to fetch contact data.");
    } else {
        // Assign the fetched contact value to userContact.
        // And use the value accordingly in the UI.
        setState(() => userContact = _contact);
    }
}
  • If user wants to delete a contact, Call deleteContact() or delete() function.

  • You can implement deleting a contact functionality using either of the functions.

    • If you use deleteContact() function, It needs the user's contact as a positional parameter.

    • If you use delete() function, It needs just the atSign of the user's contact. And it can be fetched from the user contact itself.

    • Let us see the both implementations.

/// Using `delete()` function.
Future<void> _deleteContact(String _atSign) async {
    if(_atSign == null || _atSign.isEmpty){
        print("AtSign was't passed or empty.");
    } else {
        bool _isContactDeleted = await _atContact.delete(_atSign);
        print(_isContactDeleted ? 'Contact deleted successfully' : 'Failed to delete contact.');
    }
}
/// Using `deleteContact()` function.
Future<void> _deleteContact(AtContact _contact) async {
    bool _isContactDeleted = await _atContact.deleteContact(_contact);
    print(_isContactDeleted ? 'Contact deleted successfully' : 'Failed to delete contact.');
}
  • Show the list of the user's contacts. Then call the listContacts() function.
/// In Contacts list screen, call the `listContacts()`.
List<AtContact> contactsList = await _atContact.listContacts();

// Use this contactsList in the UI part and render the data as you wish.
// Or use FutureBuilder and ListView to show the contact data as a list.
  • If the user wants to list out their favorite contacts, Then call listFavoriteContacts() function.
Future<void> _listFavoriteContacts() async {
    List<AtContact> _favContactsList = await _atContact.listFavoriteContacts();
    if(_favContactsList.isEmpty){
        print("No favorite contacts found");
    } else {
        setState(() => favContactsList = _favContactsList);
    }
}

Groups

  • So far we have looked into contacts, Now let us know how AtGroups to be used.

  • If the user wants to create a group, Then call createGroup() function where it take a AtGroup as a positional argument.

// Pass the user input data to respective fields of AtGroup.
AtGroup myGroup = AtGroup('The @platform team')
    ..createdBy = _myAtSign
    ..createdOn = DateTime.now()
    ..description = 'Team with awesome spirit'
    ..updatedOn = DateTime.now()
    ..groupId = 'T@PT101'
    ..displayName = 'at_contact team';
Future<void> _createGroup(AtGroup group) async {
    AtGroup? myGroup = await _atContact.createGroup(group);
    if(myGroup == null){
        print('Failed to create group')
    } else {
        print(group.id + ' has been created successfully');
    }
}
  • If the user wants to update a group, Then call updateGroup() function where it take a AtGroup as a positional argument.
// Pass the user input data to respective fields of AtGroup.
AtGroup myGroup = AtGroup('The @platform team')
    ..createdBy = _myAtSign
    ..createdOn = DateTime.now()
    ..description = 'Team with awesome spirit'
    ..updatedOn = DateTime.now()
    ..groupId = 'T@PT101'
    ..displayName = 'at_contact team';
Future<void> _updateGroup(AtGroup group) async {
    try{
        AtGroup? myGroup = await _atContact.updateGroup(group);
        if(myGroup == null){
            print('Failed to create group')
        } else {
            print(group.id + ' has been created successfully');
        }
    } catch(e){
        if(e is GroupNotExistsException){
            print('Group not exists. Please create the group first.');
        } else {
            print('Failed to update group');
        }
    }
}
  • If the user wants to get the details about group, Then call getGroup() function with groupID as positional argument.
String myGroupId = 'T@PT101';

Future<void> _getGroup(String groupId) async {
    AtGroup? myGroup = await _atContact.getGroup(groupName);
    if(myGroup == null){
        print('Failed to get group details')
    } else {
        print('Group Name: ${myGroup.groupName}\n'
        'Group ID : ${myGroup.groupId}\n'
        'Created by : ${myGroup.createdBy}\n'
        'Created on : ${myGroup.createdOn}');
    }
}
  • If the user wants to delete the group, Then call deleteGroup() function with AtGroup as positional argument.
Future<void> _deleteGroup(AtGroup groupName) async {
    AtGroup? _myGroup = await _atContact.getGroup(groupName);
    if(_myGroup == null){
        print('Failed to get group details');
    } else {
        bool _isGroupDeleted = await _atContact.deleteGroup(_myGroup);
        print(_isGroupDeleted ? _myGroup.groupName + ' group deleted' : 'Failed to delete group');
    }
}
  • If user wants to get the list of group names, Then call listGroupNames() function.
Future<void> _listGroupNames() async {
    List<String?> _groupNames = await _atContact.listGroupNames();
    if(_groupNames.isEmpty){
        print('No groups found');
    } else {
        // Iterate through the list and print names 
        for(String _groupName in _groupNames){
            print(_groupName);
        }
    }
}
  • If user wants to get the list of group names, Then call listGroupIds() function.
Future<void> _listGroupIds() async {
    List<String?> _groupIds = await _atContact.listGroupIds();
    if(_groupIds == null){
        print('No groups found');
    } else {
        // Iterate through the list and print ids 
        for(String _groupId in _groupIds){
            print(_groupId);
        }
    }
}
  • If user wants to add someone to the group, then call addMembers() function. This function needs Set<AtContact> and AtGroup as positional arguments.
Set<AtContact> selectedContacts = <AtContact>{};

for(String _atSign in selectedAtSignsList){
    AtContact? _fetchedContact = await _atContact.get(_atSign);
    if(_fetchedContact != null){
        selectedContacts.add(_fetchedContact);
    } else{
        print('Failed to get contact for $_atSign');
    }
}
// Get your group details if you have the group id
AtGroup? _myGroup = await _atContact.getGroup(myGroupID);

Future<void> _addMembers(Set<AtContact> contacts, AtGroup group) async {
    bool _isMembersAdded = await _atContact.addMembers(contacts, group);
    print(_isMembersAdded ? 'Members added to the group' : 'Failed to add members to the group');
}
  • If a user wants to delete a contact from the group , Then call deleteMembers() function.
Set<AtContact> selectedContacts = <AtContact>{};

for(String _atSign in selectedAtSignsList){
    AtContact? _fetchedContact = await _atContact.get(_atSign);
    if(_fetchedContact != null){
        selectedContacts.add(_fetchedContact);
    } else{
        print('Failed to get contact for $_atSign');
    }
}
AtGroup? _myGroup = await _atContact.getGroup(myGroupID);

Future<void> _deleteMembers(Set<AtContact> contacts, AtGroup group) async {
    bool _isMembersRemoved = await _atContact.deleteMembers(contacts, group);
    print(_isMembersRemoved ? 'Member removed from the group' : 'Failed to remove member from the group')
}
  • To check if the user is a member of the group you are looking for, Then call isMember() function.
AtContact? _userContact = await _atContact.get(atSign);
bool isAMember = await _atContact.isMember(_userContact, myGroup);
print(atSign + ' is ${isAMember ? '' : 'not'} a member of ' + myGroup.groupName); 
// @colin is a member of The @platform team 
// @somerandomatsign is not a member of The @Platform team

For more information, please see the API documentation listed on pub.dev.

Additional content

Open source usage and contributions

This is open source code, so feel free to use it as is, suggest changes or enhancements or create your own version. See CONTRIBUTING.md for detailed guidance on how to setup tools, tests and make a pull request.

Libraries

at_contact
Support for doing something awesome.