2019-02-10 21:25:29 +01:00
|
|
|
// import SummaryMembers from "./members";
|
2018-12-21 14:35:24 +01:00
|
|
|
|
2019-02-10 21:25:29 +01:00
|
|
|
export default class RoomSummary {
|
2019-02-04 23:30:10 +01:00
|
|
|
constructor(roomId) {
|
2019-02-10 21:25:29 +01:00
|
|
|
// this._members = new SummaryMembers();
|
2018-12-21 14:35:24 +01:00
|
|
|
this._roomId = roomId;
|
2019-02-10 21:25:29 +01:00
|
|
|
this._name = null;
|
2019-02-16 02:55:01 +01:00
|
|
|
this._lastMessageBody = null;
|
2019-02-10 21:25:29 +01:00
|
|
|
this._unreadCount = null;
|
|
|
|
this._mentionCount = null;
|
|
|
|
this._isEncrypted = null;
|
|
|
|
this._isDirectMessage = null;
|
|
|
|
this._membership = null;
|
2018-12-21 14:35:24 +01:00
|
|
|
this._inviteCount = 0;
|
|
|
|
this._joinCount = 0;
|
2019-02-16 02:55:01 +01:00
|
|
|
this._readMarkerEventId = null;
|
2019-10-13 07:48:33 +02:00
|
|
|
this._heroes = null;
|
|
|
|
this._canonicalAlias = null;
|
|
|
|
this._aliases = null;
|
2018-12-21 14:35:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
get name() {
|
2019-10-13 07:48:33 +02:00
|
|
|
if (this._name) {
|
|
|
|
return this._name;
|
|
|
|
}
|
|
|
|
if (this._canonicalAlias) {
|
|
|
|
return this._canonicalAlias;
|
|
|
|
}
|
|
|
|
if (this._aliases) {
|
|
|
|
return this._aliases[0];
|
|
|
|
}
|
|
|
|
if (this._heroes) {
|
|
|
|
return this._heroes.join(", ");
|
|
|
|
}
|
|
|
|
return this._roomId;
|
2018-12-21 14:35:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
get lastMessage() {
|
|
|
|
return this._lastMessageBody;
|
|
|
|
}
|
|
|
|
|
|
|
|
get inviteCount() {
|
|
|
|
return this._inviteCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
get joinCount() {
|
|
|
|
return this._joinCount;
|
|
|
|
}
|
|
|
|
|
2019-02-27 23:23:09 +01:00
|
|
|
applySync(roomResponse, membership, txn) {
|
2019-02-10 21:25:29 +01:00
|
|
|
const changed = this._processSyncResponse(roomResponse, membership);
|
2018-12-21 14:35:24 +01:00
|
|
|
if (changed) {
|
2019-02-27 23:23:09 +01:00
|
|
|
this._persist(txn);
|
2018-12-21 14:35:24 +01:00
|
|
|
}
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
2019-02-10 21:25:29 +01:00
|
|
|
async load(summary) {
|
2018-12-21 14:35:24 +01:00
|
|
|
this._roomId = summary.roomId;
|
2019-02-10 21:25:29 +01:00
|
|
|
this._name = summary.name;
|
2019-02-16 02:55:01 +01:00
|
|
|
this._lastMessageBody = summary.lastMessageBody;
|
2019-02-10 21:25:29 +01:00
|
|
|
this._unreadCount = summary.unreadCount;
|
|
|
|
this._mentionCount = summary.mentionCount;
|
|
|
|
this._isEncrypted = summary.isEncrypted;
|
|
|
|
this._isDirectMessage = summary.isDirectMessage;
|
|
|
|
this._membership = summary.membership;
|
2018-12-21 14:35:24 +01:00
|
|
|
this._inviteCount = summary.inviteCount;
|
|
|
|
this._joinCount = summary.joinCount;
|
2019-02-16 02:55:01 +01:00
|
|
|
this._readMarkerEventId = summary.readMarkerEventId;
|
2019-10-13 07:48:33 +02:00
|
|
|
this._heroes = summary.heroes;
|
|
|
|
this._aliases = summary.aliases;
|
|
|
|
this._canonicalAlias = summary.canonicalAlias;
|
2018-12-21 14:35:24 +01:00
|
|
|
}
|
|
|
|
|
2019-02-10 21:25:29 +01:00
|
|
|
_persist(txn) {
|
2019-02-16 02:55:01 +01:00
|
|
|
// need to think here how we want to persist
|
|
|
|
// things like unread status (as read marker, or unread count)?
|
|
|
|
// we could very well load additional things in the load method
|
|
|
|
// ... the trade-off is between constantly writing the summary
|
|
|
|
// on every sync, or doing a bit of extra reading on load
|
|
|
|
// and have in-memory only variables for visualization
|
2018-12-21 14:35:24 +01:00
|
|
|
const summary = {
|
|
|
|
roomId: this._roomId,
|
2019-02-16 02:55:01 +01:00
|
|
|
name: this._name,
|
|
|
|
lastMessageBody: this._lastMessageBody,
|
|
|
|
unreadCount: this._unreadCount,
|
|
|
|
mentionCount: this._mentionCount,
|
|
|
|
isEncrypted: this._isEncrypted,
|
|
|
|
isDirectMessage: this._isDirectMessage,
|
|
|
|
membership: this._membership,
|
2018-12-21 14:35:24 +01:00
|
|
|
inviteCount: this._inviteCount,
|
|
|
|
joinCount: this._joinCount,
|
2019-02-16 02:55:01 +01:00
|
|
|
readMarkerEventId: this._readMarkerEventId,
|
2019-10-13 07:48:33 +02:00
|
|
|
heroes: this._heroes,
|
|
|
|
aliases: this._aliases,
|
|
|
|
canonicalAlias: this._canonicalAlias,
|
2018-12-21 14:35:24 +01:00
|
|
|
};
|
2019-02-10 21:25:29 +01:00
|
|
|
return txn.roomSummary.set(summary);
|
2018-12-21 14:35:24 +01:00
|
|
|
}
|
|
|
|
|
2019-02-10 21:25:29 +01:00
|
|
|
_processSyncResponse(roomResponse, membership) {
|
2018-12-21 14:35:24 +01:00
|
|
|
let changed = false;
|
2019-10-13 07:48:33 +02:00
|
|
|
if (roomResponse.summary) {
|
|
|
|
this._updateSummary(roomResponse.summary);
|
|
|
|
changed = true;
|
|
|
|
}
|
2019-02-10 21:25:29 +01:00
|
|
|
if (membership !== this._membership) {
|
|
|
|
this._membership = membership;
|
|
|
|
changed = true;
|
|
|
|
}
|
2019-02-27 22:50:08 +01:00
|
|
|
// state comes before timeline
|
2019-02-16 00:47:24 +01:00
|
|
|
if (roomResponse.state) {
|
|
|
|
changed = roomResponse.state.events.reduce((changed, e) => {
|
2018-12-21 14:35:24 +01:00
|
|
|
return this._processEvent(e) || changed;
|
|
|
|
}, changed);
|
|
|
|
}
|
2019-02-10 21:25:29 +01:00
|
|
|
if (roomResponse.timeline) {
|
|
|
|
changed = roomResponse.timeline.events.reduce((changed, e) => {
|
|
|
|
return this._processEvent(e) || changed;
|
|
|
|
}, changed);
|
|
|
|
}
|
2018-12-21 14:35:24 +01:00
|
|
|
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
_processEvent(event) {
|
2019-02-16 02:55:01 +01:00
|
|
|
if (event.type === "m.room.encryption") {
|
|
|
|
if (!this._isEncrypted) {
|
|
|
|
this._isEncrypted = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2018-12-21 14:35:24 +01:00
|
|
|
if (event.type === "m.room.name") {
|
|
|
|
const newName = event.content && event.content.name;
|
2019-02-10 21:25:29 +01:00
|
|
|
if (newName !== this._name) {
|
|
|
|
this._name = newName;
|
2018-12-21 14:35:24 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else if (event.type === "m.room.member") {
|
|
|
|
return this._processMembership(event);
|
|
|
|
} else if (event.type === "m.room.message") {
|
|
|
|
const content = event.content;
|
|
|
|
const body = content && content.body;
|
|
|
|
const msgtype = content && content.msgtype;
|
|
|
|
if (msgtype === "m.text") {
|
|
|
|
this._lastMessageBody = body;
|
|
|
|
return true;
|
|
|
|
}
|
2019-10-13 07:48:33 +02:00
|
|
|
} else if (event.type === "m.room.canonical_alias") {
|
|
|
|
const content = event.content;
|
|
|
|
this._canonicalAlias = content.alias;
|
|
|
|
return true;
|
|
|
|
} else if (event.type === "m.room.aliases") {
|
|
|
|
const content = event.content;
|
|
|
|
this._aliases = content.aliases;
|
|
|
|
return true;
|
|
|
|
}
|
2018-12-21 14:35:24 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_processMembership(event) {
|
|
|
|
let changed = false;
|
|
|
|
const prevMembership = event.prev_content && event.prev_content.membership;
|
2019-02-10 21:25:29 +01:00
|
|
|
if (!event.content) {
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
const content = event.content;
|
|
|
|
const membership = content.membership;
|
2018-12-21 14:35:24 +01:00
|
|
|
// danger of a replayed event getting the count out of sync
|
|
|
|
// but summary api will solve this.
|
|
|
|
// otherwise we'd have to store all the member ids in here
|
|
|
|
if (membership !== prevMembership) {
|
|
|
|
switch (prevMembership) {
|
2019-02-10 21:25:29 +01:00
|
|
|
case "invite": --this._inviteCount; break;
|
|
|
|
case "join": --this._joinCount; break;
|
2018-12-21 14:35:24 +01:00
|
|
|
}
|
|
|
|
switch (membership) {
|
2019-02-10 21:25:29 +01:00
|
|
|
case "invite": ++this._inviteCount; break;
|
|
|
|
case "join": ++this._joinCount; break;
|
2018-12-21 14:35:24 +01:00
|
|
|
}
|
|
|
|
changed = true;
|
|
|
|
}
|
2019-02-10 21:25:29 +01:00
|
|
|
// if (membership === "join" && content.name) {
|
|
|
|
// // TODO: avatar_url
|
|
|
|
// changed = this._members.applyMember(content.name, content.state_key) || changed;
|
|
|
|
// }
|
2018-12-21 14:35:24 +01:00
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
_updateSummary(summary) {
|
|
|
|
const heroes = summary["m.heroes"];
|
|
|
|
const inviteCount = summary["m.joined_member_count"];
|
|
|
|
const joinCount = summary["m.invited_member_count"];
|
|
|
|
|
|
|
|
if (heroes) {
|
|
|
|
this._heroes = heroes;
|
|
|
|
}
|
|
|
|
if (Number.isInteger(inviteCount)) {
|
|
|
|
this._inviteCount = inviteCount;
|
|
|
|
}
|
|
|
|
if (Number.isInteger(joinCount)) {
|
|
|
|
this._joinCount = joinCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|