mirror of
https://github.com/vector-im/hydrogen-web.git
synced 2024-12-23 19:45:05 +01:00
reference count archived rooms and keep track of active ones
so we don't create two instances for the same id, one for sync, and one for displaying, and hence updates from sync being pushed on a different instance than the one displaying, and not updating the view.
This commit is contained in:
parent
965700272b
commit
8b8214cd1b
@ -81,6 +81,9 @@ export class RoomViewModel extends ViewModel {
|
|||||||
dispose() {
|
dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
this._room.off("change", this._onRoomChange);
|
this._room.off("change", this._onRoomChange);
|
||||||
|
if (this._room.isArchived) {
|
||||||
|
this._room.release();
|
||||||
|
}
|
||||||
if (this._clearUnreadTimout) {
|
if (this._clearUnreadTimout) {
|
||||||
this._clearUnreadTimout.abort();
|
this._clearUnreadTimout.abort();
|
||||||
this._clearUnreadTimout = null;
|
this._clearUnreadTimout = null;
|
||||||
|
@ -56,6 +56,7 @@ export class Session {
|
|||||||
this._sessionInfo = sessionInfo;
|
this._sessionInfo = sessionInfo;
|
||||||
this._rooms = new ObservableMap();
|
this._rooms = new ObservableMap();
|
||||||
this._roomUpdateCallback = (room, params) => this._rooms.update(room.id, params);
|
this._roomUpdateCallback = (room, params) => this._rooms.update(room.id, params);
|
||||||
|
this._activeArchivedRooms = new Map();
|
||||||
this._invites = new ObservableMap();
|
this._invites = new ObservableMap();
|
||||||
this._inviteUpdateCallback = (invite, params) => this._invites.update(invite.id, params);
|
this._inviteUpdateCallback = (invite, params) => this._invites.update(invite.id, params);
|
||||||
this._user = new User(sessionInfo.userId);
|
this._user = new User(sessionInfo.userId);
|
||||||
@ -399,18 +400,21 @@ export class Session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
createArchivedRoom(roomId) {
|
_createArchivedRoom(roomId) {
|
||||||
return new ArchivedRoom({
|
const room = new ArchivedRoom({
|
||||||
roomId,
|
roomId,
|
||||||
getSyncToken: this._getSyncToken,
|
getSyncToken: this._getSyncToken,
|
||||||
storage: this._storage,
|
storage: this._storage,
|
||||||
emitCollectionChange: () => {},
|
emitCollectionChange: () => {},
|
||||||
|
releaseCallback: () => this._activeArchivedRooms.delete(roomId),
|
||||||
hsApi: this._hsApi,
|
hsApi: this._hsApi,
|
||||||
mediaRepository: this._mediaRepository,
|
mediaRepository: this._mediaRepository,
|
||||||
user: this._user,
|
user: this._user,
|
||||||
createRoomEncryption: this._createRoomEncryption,
|
createRoomEncryption: this._createRoomEncryption,
|
||||||
platform: this._platform
|
platform: this._platform
|
||||||
});
|
});
|
||||||
|
this._activeArchivedRooms.set(roomId, room);
|
||||||
|
return room;
|
||||||
}
|
}
|
||||||
|
|
||||||
get invites() {
|
get invites() {
|
||||||
@ -641,6 +645,8 @@ export class Session {
|
|||||||
return RoomStatus.joined;
|
return RoomStatus.joined;
|
||||||
} else {
|
} else {
|
||||||
const isInvited = !!this._invites.get(roomId);
|
const isInvited = !!this._invites.get(roomId);
|
||||||
|
const txn = await this._storage.readTxn([this._storage.storeNames.archivedRoomSummary]);
|
||||||
|
const isArchived = await txn.archivedRoomSummary.has(roomId);
|
||||||
if (isInvited && isArchived) {
|
if (isInvited && isArchived) {
|
||||||
return RoomStatus.invitedAndArchived;
|
return RoomStatus.invitedAndArchived;
|
||||||
} else if (isInvited) {
|
} else if (isInvited) {
|
||||||
@ -668,13 +674,18 @@ export class Session {
|
|||||||
loadArchivedRoom(roomId, log = null) {
|
loadArchivedRoom(roomId, log = null) {
|
||||||
return this._platform.logger.wrapOrRun(log, "loadArchivedRoom", async log => {
|
return this._platform.logger.wrapOrRun(log, "loadArchivedRoom", async log => {
|
||||||
log.set("id", roomId);
|
log.set("id", roomId);
|
||||||
|
const activeArchivedRoom = this._activeArchivedRooms.get(roomId);
|
||||||
|
if (activeArchivedRoom) {
|
||||||
|
activeArchivedRoom.retain();
|
||||||
|
return activeArchivedRoom;
|
||||||
|
}
|
||||||
const txn = await this._storage.readTxn([
|
const txn = await this._storage.readTxn([
|
||||||
this._storage.storeNames.archivedRoomSummary,
|
this._storage.storeNames.archivedRoomSummary,
|
||||||
this._storage.storeNames.roomMembers,
|
this._storage.storeNames.roomMembers,
|
||||||
]);
|
]);
|
||||||
const summary = await txn.archivedRoomSummary.get(roomId);
|
const summary = await txn.archivedRoomSummary.get(roomId);
|
||||||
if (summary) {
|
if (summary) {
|
||||||
const room = this.createArchivedRoom(roomId);
|
const room = this._createArchivedRoom(roomId);
|
||||||
await room.load(summary, txn, log);
|
await room.load(summary, txn, log);
|
||||||
return room;
|
return room;
|
||||||
}
|
}
|
||||||
|
@ -309,7 +309,10 @@ export class Sync {
|
|||||||
_afterSync(sessionState, inviteStates, roomStates, archivedRoomStates, log) {
|
_afterSync(sessionState, inviteStates, roomStates, archivedRoomStates, log) {
|
||||||
log.wrap("session", log => this._session.afterSync(sessionState.changes, log), log.level.Detail);
|
log.wrap("session", log => this._session.afterSync(sessionState.changes, log), log.level.Detail);
|
||||||
for(let ars of archivedRoomStates) {
|
for(let ars of archivedRoomStates) {
|
||||||
log.wrap("archivedRoom", log => ars.archivedRoom.afterSync(ars.changes, log), log.level.Detail);
|
log.wrap("archivedRoom", log => {
|
||||||
|
ars.archivedRoom.afterSync(ars.changes, log);
|
||||||
|
ars.archivedRoom.release();
|
||||||
|
}, log.level.Detail);
|
||||||
}
|
}
|
||||||
for(let rs of roomStates) {
|
for(let rs of roomStates) {
|
||||||
log.wrap("room", log => rs.room.afterSync(rs.changes, log), log.level.Detail);
|
log.wrap("room", log => rs.room.afterSync(rs.changes, log), log.level.Detail);
|
||||||
@ -407,12 +410,12 @@ export class Sync {
|
|||||||
// when adding a joined room during incremental sync,
|
// when adding a joined room during incremental sync,
|
||||||
// always create the archived room to write the removal
|
// always create the archived room to write the removal
|
||||||
// of the archived summary
|
// of the archived summary
|
||||||
archivedRoom = this._session.createArchivedRoom(roomId);
|
archivedRoom = await this._session.loadArchivedRoom(roomId, log);
|
||||||
} else if (membership === "leave") {
|
} else if (membership === "leave") {
|
||||||
if (roomState) {
|
if (roomState) {
|
||||||
// we still have a roomState, so we just left it
|
// we still have a roomState, so we just left it
|
||||||
// in this case, create a new archivedRoom
|
// in this case, create a new archivedRoom
|
||||||
archivedRoom = this._session.createArchivedRoom(roomId);
|
archivedRoom = await this._session.loadArchivedRoom(roomId, log);
|
||||||
} else {
|
} else {
|
||||||
// this is an update of an already left room, restore
|
// this is an update of an already left room, restore
|
||||||
// it from storage first, so we can increment it.
|
// it from storage first, so we can increment it.
|
||||||
|
@ -21,6 +21,10 @@ import {RoomMember} from "./members/RoomMember.js";
|
|||||||
export class ArchivedRoom extends BaseRoom {
|
export class ArchivedRoom extends BaseRoom {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
|
// archived rooms are reference counted,
|
||||||
|
// as they are not kept in memory when not needed
|
||||||
|
this._releaseCallback = options.releaseCallback;
|
||||||
|
this._retentionCount = 1;
|
||||||
/**
|
/**
|
||||||
Some details from our own member event when being kicked or banned.
|
Some details from our own member event when being kicked or banned.
|
||||||
We can't get this from the member store, because we don't store the reason field there.
|
We can't get this from the member store, because we don't store the reason field there.
|
||||||
@ -29,6 +33,17 @@ export class ArchivedRoom extends BaseRoom {
|
|||||||
this._kickedBy = null;
|
this._kickedBy = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retain() {
|
||||||
|
this._retentionCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
release() {
|
||||||
|
this._retentionCount -= 1;
|
||||||
|
if (this._retentionCount === 0) {
|
||||||
|
this._releaseCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async _getKickAuthor(sender, txn) {
|
async _getKickAuthor(sender, txn) {
|
||||||
const senderMember = await txn.roomMembers.get(this.id, sender);
|
const senderMember = await txn.roomMembers.get(this.id, sender);
|
||||||
if (senderMember) {
|
if (senderMember) {
|
||||||
|
Loading…
Reference in New Issue
Block a user