Sharing Objects


ZeroDark.cloud has extensive support for sharing your app's objects.

WRITE ME

Management of remote users.

The pushSharedUsersView function from ZeroDark.cloud uiTools is provides a view controller which displays and allows a local user to manage which remote users a node is shared with. You provide the function your localUserID as well as the existing list of remote user IDs you are sharing to. On iOS you also provide a UINavigationController you want the view controller pushed onto. The pushSharedUsersView will take care of the rest, allowing your user to search for remote users, add them as well as remove existing one. It will call you back when the user completes with a set of new user IDs as well as a set of user IDs removed. You can then use this information to modify the shared objects node sharing permissions

Calling the pushSharedUsersView

let zdc = ZDCManager.zdc()
let localUserID =  // your localUserID

// get an array of remoteUserIDs we are already sharing this node with.
var node: ZDCNode? = nil
databaseConnection.read { (transaction) in
    if let cloudTransaction = zdc.cloudTransaction(transaction, forLocalUserID: self.localUserID) {
        node = cloudTransaction.linkedNode(forKey: yourSharedObjectID,
                                       inCollection: kYourCollectionID)
    }
}
let remoteUserIDs = node?.shareList.allUserIDs() ?? []

// push a shared user View and ask for changes.
ZDCManager.uiTools().pushSharedUsersView(forLocalUserID: localUserID,
                                                      remoteUserIDs: Set(remoteUserIDs),
                                                      title: "Shared To",
                                                      navigationController: self.navigationController!)
{ (newUsers:Set<String>?, removedUsers:Set<String>?) in

 // code to modify your object's sharing permissions 
 // with the newUsers and removedUsers

    self.modifyListPermissions(yourSharedObjectID,
                                localUserID  : self.localUserID,
                                newUsers     : newUsers ?? Set<String>(),
                                removedUsers : removedUsers ?? Set<String>())

}

Changing the node's permissions as a result of the pushSharedUsersView

 func modifyObjectPermissions(_ objectID     : String,
                                 localUserID  : String,
                                 newUsers     : Set<String>,
                                 removedUsers : Set<String>)
{
    if (newUsers.count == 0) && (removedUsers.count == 0) {
        return
    }

    let zdc = ZDCManager.zdc()
    let rwConnection = zdc.databaseManager!.rwDatabaseConnection
    rwConnection.asyncReadWrite({ (transaction) in

        guard let cloudTransaction = zdc.cloudTransaction(transaction, forLocalUserID: localUserID) else {

            return
        }

        if var node = cloudTransaction.linkedNode(forKey: objectID, inCollection: kYourCollectionID) {

            node = node.copy() as! ZDCNode

            for addedUserID in newUsers {
                let shareItem = ZDCShareItem()
                shareItem.addPermission(ZDCSharePermission.read)
                node.shareList.add(shareItem, forUserID: addedUserID)
            }

            for removedUserID in removedUsers {
                node.shareList.removeShareItem(forUserID: removedUserID)
            }

            do {
                try cloudTransaction.modifyNode(node)

            } catch {

                print("Error modifying node: \(error)")
                return // from transaction
            }
        }

// Modifying the node indirectly modifies the Object.
// And there are various components of our UI that should update in response to this change.
// However, those UI components are looking for changes to the List, not to the node.
// So what we want to do here is tell the database that the Object was modified.
// This way, when the DatabaseModified notification gets sent out,
// our UI will update the Object properly.
//
// We can accomplish this using YapDatabase's `touch` functionality.

        transaction.touchObject(forKey: objectID, inCollection: kYourCollectionID)

        // Todo: You should also send a message to the user(s) we added.
    })
}

Searching for users

Screenshot