Sync breadcrumb rooms through account data
Fixes https://github.com/vector-im/riot-web/issues/9315 Other clients would need to listen for and update im.vector.riot.breadcrumb_rooms in account data.
This commit is contained in:
parent
37afa9fc0e
commit
44198ea97d
3 changed files with 94 additions and 24 deletions
|
@ -24,6 +24,7 @@ import classNames from 'classnames';
|
||||||
import sdk from "../../../index";
|
import sdk from "../../../index";
|
||||||
import * as RoomNotifs from '../../../RoomNotifs';
|
import * as RoomNotifs from '../../../RoomNotifs';
|
||||||
import * as FormattingUtils from "../../../utils/FormattingUtils";
|
import * as FormattingUtils from "../../../utils/FormattingUtils";
|
||||||
|
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||||
|
|
||||||
const MAX_ROOMS = 20;
|
const MAX_ROOMS = 20;
|
||||||
|
|
||||||
|
@ -38,22 +39,22 @@ export default class RoomBreadcrumbs extends React.Component {
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this._dispatcherRef = dis.register(this.onAction);
|
this._dispatcherRef = dis.register(this.onAction);
|
||||||
|
|
||||||
|
let storedRooms = SettingsStore.getValue("breadcrumb_rooms");
|
||||||
|
if (!storedRooms || !storedRooms.length) {
|
||||||
|
// Fallback to the rooms stored in localstorage for those who would have had this.
|
||||||
|
// TODO: Remove this after a bit - the feature was only on develop, so a few weeks should be plenty time.
|
||||||
const roomStr = localStorage.getItem("mx_breadcrumb_rooms");
|
const roomStr = localStorage.getItem("mx_breadcrumb_rooms");
|
||||||
if (roomStr) {
|
if (roomStr) {
|
||||||
try {
|
try {
|
||||||
const roomIds = JSON.parse(roomStr);
|
storedRooms = JSON.parse(roomStr);
|
||||||
this.setState({
|
|
||||||
rooms: roomIds.map((r) => {
|
|
||||||
return {
|
|
||||||
room: MatrixClientPeg.get().getRoom(r),
|
|
||||||
animated: false,
|
|
||||||
};
|
|
||||||
}).filter((r) => r.room),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to parse breadcrumbs:", e);
|
console.error("Failed to parse breadcrumbs:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
this._loadRoomIds(storedRooms || []);
|
||||||
|
|
||||||
|
this._settingWatchRef = SettingsStore.watchSetting("breadcrumb_rooms", null, this.onBreadcrumbsChanged);
|
||||||
|
|
||||||
MatrixClientPeg.get().on("Room.myMembership", this.onMyMembership);
|
MatrixClientPeg.get().on("Room.myMembership", this.onMyMembership);
|
||||||
MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt);
|
MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt);
|
||||||
|
@ -64,6 +65,8 @@ export default class RoomBreadcrumbs extends React.Component {
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
dis.unregister(this._dispatcherRef);
|
dis.unregister(this._dispatcherRef);
|
||||||
|
|
||||||
|
SettingsStore.unwatchSetting(this._settingWatchRef);
|
||||||
|
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
if (client) {
|
if (client) {
|
||||||
client.removeListener("Room.myMembership", this.onMyMembership);
|
client.removeListener("Room.myMembership", this.onMyMembership);
|
||||||
|
@ -84,8 +87,8 @@ export default class RoomBreadcrumbs extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const roomStr = JSON.stringify(rooms.map((r) => r.room.roomId));
|
const roomIds = rooms.map((r) => r.room.roomId);
|
||||||
localStorage.setItem("mx_breadcrumb_rooms", roomStr);
|
SettingsStore.setValue("breadcrumb_rooms", null, SettingLevel.ACCOUNT, roomIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAction(payload) {
|
onAction(payload) {
|
||||||
|
@ -125,17 +128,48 @@ export default class RoomBreadcrumbs extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_calculateRoomBadges(room) {
|
onBreadcrumbsChanged = (settingName, roomId, level, valueAtLevel, value) => {
|
||||||
if (!room) return;
|
if (!value) return;
|
||||||
|
|
||||||
const rooms = this.state.rooms.slice();
|
const currentState = this.state.rooms.map((r) => r.room.roomId);
|
||||||
const roomModel = rooms.find((r) => r.room.roomId === room.roomId);
|
if (currentState.length === value.length) {
|
||||||
if (!roomModel) return; // No applicable room, so don't do math on it
|
let changed = false;
|
||||||
|
for (let i = 0; i < currentState.length; i++) {
|
||||||
|
if (currentState[i] !== value[i]) {
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!changed) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._loadRoomIds(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
_loadRoomIds(roomIds) {
|
||||||
|
// If we're here, the list changed.
|
||||||
|
const rooms = roomIds.map((r) => MatrixClientPeg.get().getRoom(r)).filter((r) => r).map((r) => {
|
||||||
|
const badges = this._calculateBadgesForRoom(r) || {};
|
||||||
|
return {
|
||||||
|
room: r,
|
||||||
|
animated: false,
|
||||||
|
...badges,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
this.setState({
|
||||||
|
rooms: rooms,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_calculateBadgesForRoom(room) {
|
||||||
|
if (!room) return null;
|
||||||
|
|
||||||
// Reset the notification variables for simplicity
|
// Reset the notification variables for simplicity
|
||||||
roomModel.redBadge = false;
|
const roomModel = {
|
||||||
roomModel.formattedCount = "0";
|
redBadge: false,
|
||||||
roomModel.showCount = false;
|
formattedCount: "0",
|
||||||
|
showCount: false,
|
||||||
|
};
|
||||||
|
|
||||||
const notifState = RoomNotifs.getRoomNotifsState(room.roomId);
|
const notifState = RoomNotifs.getRoomNotifsState(room.roomId);
|
||||||
if (RoomNotifs.MENTION_BADGE_STATES.includes(notifState)) {
|
if (RoomNotifs.MENTION_BADGE_STATES.includes(notifState)) {
|
||||||
|
@ -155,6 +189,20 @@ export default class RoomBreadcrumbs extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return roomModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
_calculateRoomBadges(room) {
|
||||||
|
if (!room) return;
|
||||||
|
|
||||||
|
const rooms = this.state.rooms.slice();
|
||||||
|
const roomModel = rooms.find((r) => r.room.roomId === room.roomId);
|
||||||
|
if (!roomModel) return; // No applicable room, so don't do math on it
|
||||||
|
|
||||||
|
const badges = this._calculateBadgesForRoom(room);
|
||||||
|
if (!badges) return; // No badges for some reason
|
||||||
|
|
||||||
|
Object.assign(roomModel, badges);
|
||||||
this.setState({rooms});
|
this.setState({rooms});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -258,6 +258,10 @@ export const SETTINGS = {
|
||||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||||
default: "en",
|
default: "en",
|
||||||
},
|
},
|
||||||
|
"breadcrumb_rooms": {
|
||||||
|
supportedLevels: ['account'],
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
"analyticsOptIn": {
|
"analyticsOptIn": {
|
||||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||||
displayName: _td('Send analytics data'),
|
displayName: _td('Send analytics data'),
|
||||||
|
|
|
@ -19,6 +19,8 @@ import MatrixClientPeg from '../../MatrixClientPeg';
|
||||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||||
import {SettingLevel} from "../SettingsStore";
|
import {SettingLevel} from "../SettingsStore";
|
||||||
|
|
||||||
|
const BREADCRUMBS_EVENT_TYPE = "im.vector.riot.breadcrumb_rooms";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets and sets settings at the "account" level for the current user.
|
* Gets and sets settings at the "account" level for the current user.
|
||||||
* This handler does not make use of the roomId parameter.
|
* This handler does not make use of the roomId parameter.
|
||||||
|
@ -55,6 +57,9 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
const val = event.getContent()[settingName];
|
const val = event.getContent()[settingName];
|
||||||
this._watchers.notifyUpdate(settingName, null, SettingLevel.ACCOUNT, val);
|
this._watchers.notifyUpdate(settingName, null, SettingLevel.ACCOUNT, val);
|
||||||
}
|
}
|
||||||
|
} else if (event.getType() === BREADCRUMBS_EVENT_TYPE) {
|
||||||
|
const val = event.getContent()['rooms'] || [];
|
||||||
|
this._watchers.notifyUpdate("breadcrumb_rooms", null, SettingLevel.ACCOUNT, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +73,12 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
return !content['disable'];
|
return !content['disable'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case for breadcrumbs
|
||||||
|
if (settingName === "breadcrumb_rooms") {
|
||||||
|
const content = this._getSettings(BREADCRUMBS_EVENT_TYPE) || {};
|
||||||
|
return content['rooms'] || [];
|
||||||
|
}
|
||||||
|
|
||||||
const settings = this._getSettings() || {};
|
const settings = this._getSettings() || {};
|
||||||
let preferredValue = settings[settingName];
|
let preferredValue = settings[settingName];
|
||||||
|
|
||||||
|
@ -89,6 +100,13 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
return MatrixClientPeg.get().setAccountData("org.matrix.preview_urls", content);
|
return MatrixClientPeg.get().setAccountData("org.matrix.preview_urls", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case for breadcrumbs
|
||||||
|
if (settingName === "breadcrumb_rooms") {
|
||||||
|
const content = this._getSettings(BREADCRUMBS_EVENT_TYPE) || {};
|
||||||
|
content['rooms'] = newValue;
|
||||||
|
return MatrixClientPeg.get().setAccountData(BREADCRUMBS_EVENT_TYPE, content);
|
||||||
|
}
|
||||||
|
|
||||||
const content = this._getSettings() || {};
|
const content = this._getSettings() || {};
|
||||||
content[settingName] = newValue;
|
content[settingName] = newValue;
|
||||||
return MatrixClientPeg.get().setAccountData("im.vector.web.settings", content);
|
return MatrixClientPeg.get().setAccountData("im.vector.web.settings", content);
|
||||||
|
|
Loading…
Reference in a new issue