Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support global account_data #150

Merged
merged 4 commits into from
Jul 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 43 additions & 18 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,37 @@ MatrixClient.prototype.getUsers = function() {
return this.store.getUsers();
};

// User Account Data operations
// ============================

/**
* Set account data event for the current user.
* @param {string} eventType The event type
* @param {Object} content the contents object for the event
* @param {module:client.callback} callback Optional.
* @return {module:client.Promise} Resolves: TODO
* @return {module:http-api.MatrixError} Rejects: with an error response.
*/
MatrixClient.prototype.setAccountData = function(eventType, contents, callback) {
var path = utils.encodeUri("/user/$userId/account_data/$type", {
$userId: this.credentials.userId,
$type: eventType,
});
return this._http.authedRequest(
callback, "PUT", path, undefined, contents
);
};

/**
* Get account data event of given type for the current user.
* @param {string} eventType The event type
* @param {module:client.callback} callback Optional.
* @return {?object} The contents of the given account data event
*/
MatrixClient.prototype.getAccountData = function(eventType) {
return this.store.getAccountData(eventType);
};

// Room operations
// ===============

Expand Down Expand Up @@ -1086,23 +1117,6 @@ MatrixClient.prototype.deleteRoomTag = function(roomId, tagName, callback) {
);
};

/**
* @param {string} eventType event type to be set
* @param {object} content event content
* @param {module:client.callback} callback Optional.
* @return {module:client.Promise} Resolves: TODO
* @return {module:http-api.MatrixError} Rejects: with an error response.
*/
MatrixClient.prototype.setAccountData = function(eventType, content, callback) {
var path = utils.encodeUri("/user/$userId/account_data/$type", {
$userId: this.credentials.userId,
$type: eventType,
});
return this._http.authedRequest(
callback, "PUT", path, undefined, content
);
};

/**
* @param {string} roomId
* @param {string} eventType event type to be set
Expand Down Expand Up @@ -3991,7 +4005,7 @@ module.exports.CRYPTO_ENABLED = CRYPTO_ENABLED;
* });
*/

/**
/**
* Fires when a device is marked as verified/unverified/blocked/unblocked by
* {@link module:client~MatrixClient#setDeviceVerified|MatrixClient.setDeviceVerified} or
* {@link module:client~MatrixClient#setDeviceBlocked|MatrixClient.setDeviceBlocked}.
Expand All @@ -4001,6 +4015,17 @@ module.exports.CRYPTO_ENABLED = CRYPTO_ENABLED;
* @param {module:client~DeviceInfo} device information about the verified device
*/

/**
* Fires whenever new user-scoped account_data is added.
* @event module:client~MatrixClient#"Room"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be module:client~MatrixClient#"accountData" ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bah didn't spot that! Yes it should be.

* @param {MatrixEvent} event The event describing the account_data just added
Copy link
Member

@kegsay kegsay Jul 20, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The event describing the account_data just added

(emph mine)

This is technically incorrect. The sync.js code will emit an accountData event before it is added to the store (and hence gettable from MatrixClient.getAccountData. If this is intentional, please update this line to state that this describes the account_data about to be added. If this is not intentional, then please tweak sync.js:611 to emit events after they have been added to the store.

There isn't a right answer as to whether you should emit before or after adding to the store, it greatly depends on what the purpose is of the thing you're emitting. This only works if you emit before for example:

MatrixClient.on("accountData", function(event) {
  if (event.getType() === "one.to.one.room") {
    // find the old 1:1 room
    var oldEvent = client.getAccountData("one.to.one.room");
  }
});

* @example
* matrixClient.on("accountData", function(event){
* myAccountData[event.type] = event.content;
* });
*/


// EventEmitter JSDocs

/**
Expand Down
27 changes: 26 additions & 1 deletion lib/store/memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ module.exports.MatrixInMemoryStore = function MatrixInMemoryStore(opts) {
// filterId: Filter
// }
};
this.accountData = {
// type : content
};
this.localStorage = opts.localStorage;
};

Expand Down Expand Up @@ -244,7 +247,29 @@ module.exports.MatrixInMemoryStore.prototype = {
this.localStorage.setItem("mxjssdk_memory_filter_" + filterName, filterId);
}
catch (e) {}
}
},

/**
* Store user-scoped account data events.
* N.B. that account data only allows a single event per type, so multiple
* events with the same type will replace each other.
* @param {Array<MatrixEvent>} events The events to store.
*/
storeAccountDataEvents: function(events) {
var self = this;
events.forEach(function(event) {
self.accountData[event.getType()] = event;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this is somewhat surprising that storeAccountDataEvents(Event[]) doesn't actually store all the events in the array if there are >1 events with the same type, but instead clobbers with the latest one. I assume this is intentional behaviour, so we should mention the clobbering semantics in the functions docs.

});
},

/**
* Get account data event by event type
* @param {string} eventType The event type being queried
* @return {?MatrixEvent} the user account_data event of given type, if any
*/
getAccountData: function(eventType) {
return this.accountData[eventType];
},

// TODO
//setMaxHistoryPerRoom: function(maxHistory) {},
Expand Down
18 changes: 17 additions & 1 deletion lib/store/stub.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,23 @@ StubStore.prototype = {
*/
setFilterIdByName: function(filterName, filterId) {

}
},

/**
* Store user-scoped account data events
* @param {Array<MatrixEvent>} events The events to store.
*/
storeAccountDataEvents: function(events) {

},

/**
* Get account data event by event type
* @param {string} eventType The event type being queried
*/
getAccountData: function(eventType) {

},

// TODO
//setMaxHistoryPerRoom: function(maxHistory) {},
Expand Down
15 changes: 14 additions & 1 deletion lib/sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ SyncApi.prototype.createRoom = function(roomId) {
"Room.receipt", "Room.tags",
"Room.timelineReset",
"Room.localEchoUpdated",
"Room.accountData",
]);
this._registerStateListeners(room);
return room;
Expand Down Expand Up @@ -605,7 +606,19 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
});
}

// the returned json structure is abit crap, so make it into a
// handle non-room account_data
if (data.account_data && utils.isArray(data.account_data.events)) {
var events = data.account_data.events.map(client.getEventMapper());
client.store.storeAccountDataEvents(events);
events.forEach(
function(accountDataEvent) {
client.emit("accountData", accountDataEvent);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it feels odd to me that our events to date have started with capital letters.

return accountDataEvent;
}
);
}

// the returned json structure is a bit crap, so make it into a
// nicer form (array) after applying sanity to make sure we don't fail
// on missing keys (on the off chance)
var inviteRooms = [];
Expand Down