Don't reference the notification levels by colour (#12138)
* Don't reference the notification levels by colour We're about to change what colours they are so either we'd have to rename a bunch of constants. We may as well make things not reference what colour anything is in the actual UI. Hopefully these constants are clear enough. * Rename NotificationColor -> NotificationLevel * Red -> Highlight * Grey -> Notification * Bold -> Activity * Anywhere else that calls it 'color' -> 'level' Also fixes some weird mixes of US & UK English. It turns out this is referenced in... quite a lot of places, so this is quite a large PR. It can't really be much smaller, sorry. * One test rename & some hiding due to ts-ignore * More hiding behind ts-ignore * Damn you, @ts-ignore... * Fix test CSS values * Missed some colour -> level Co-authored-by: Florian Duros <florianduros@element.io> * Change other instances of variables renamed in suggestion * Update new test for renames --------- Co-authored-by: Florian Duros <florianduros@element.io>
This commit is contained in:
co-authored by
Florian Duros
parent
97339ee2f6
commit
9254e9562e
@@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
import { Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { NotificationColor } from "./NotificationColor";
|
||||
import { NotificationLevel } from "./NotificationLevel";
|
||||
import { arrayDiff } from "../../utils/arrays";
|
||||
import { RoomNotificationState } from "./RoomNotificationState";
|
||||
import { NotificationState, NotificationStateEvents } from "./NotificationState";
|
||||
@@ -35,7 +35,7 @@ export class ListNotificationState extends NotificationState {
|
||||
}
|
||||
|
||||
public get symbol(): string | null {
|
||||
return this._color === NotificationColor.Unsent ? "!" : null;
|
||||
return this._level === NotificationLevel.Unsent ? "!" : null;
|
||||
}
|
||||
|
||||
public setRooms(rooms: Room[]): void {
|
||||
@@ -86,14 +86,14 @@ export class ListNotificationState extends NotificationState {
|
||||
const snapshot = this.snapshot();
|
||||
|
||||
if (this.byTileCount) {
|
||||
this._color = NotificationColor.Red;
|
||||
this._level = NotificationLevel.Highlight;
|
||||
this._count = this.rooms.length;
|
||||
} else {
|
||||
this._count = 0;
|
||||
this._color = NotificationColor.None;
|
||||
this._level = NotificationLevel.None;
|
||||
for (const state of Object.values(this.states)) {
|
||||
this._count += state.count;
|
||||
this._color = Math.max(this.color, state.color);
|
||||
this._level = Math.max(this.level, state.level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-18
@@ -16,30 +16,30 @@ limitations under the License.
|
||||
|
||||
import { _t } from "../../languageHandler";
|
||||
|
||||
export enum NotificationColor {
|
||||
export enum NotificationLevel {
|
||||
Muted,
|
||||
// Inverted (None -> Red) because we do integer comparisons on this
|
||||
None, // nothing special
|
||||
// TODO: Remove bold with notifications: https://github.com/vector-im/element-web/issues/14227
|
||||
Bold, // no badge, show as unread
|
||||
Grey, // unread notified messages
|
||||
Red, // unread pings
|
||||
Activity, // no badge, show as unread
|
||||
Notification, // unread notified messages
|
||||
Highlight, // unread pings
|
||||
Unsent, // some messages failed to send
|
||||
}
|
||||
|
||||
export function humanReadableNotificationColor(color: NotificationColor): string {
|
||||
switch (color) {
|
||||
case NotificationColor.None:
|
||||
return _t("notifications|colour_none");
|
||||
case NotificationColor.Bold:
|
||||
return _t("notifications|colour_bold");
|
||||
case NotificationColor.Grey:
|
||||
return _t("notifications|colour_grey");
|
||||
case NotificationColor.Red:
|
||||
return _t("notifications|colour_red");
|
||||
case NotificationColor.Unsent:
|
||||
return _t("notifications|colour_unsent");
|
||||
case NotificationColor.Muted:
|
||||
return _t("notifications|colour_muted");
|
||||
export function humanReadableNotificationLevel(level: NotificationLevel): string {
|
||||
switch (level) {
|
||||
case NotificationLevel.None:
|
||||
return _t("notifications|level_none");
|
||||
case NotificationLevel.Activity:
|
||||
return _t("notifications|level_activity");
|
||||
case NotificationLevel.Notification:
|
||||
return _t("notifications|level_notification");
|
||||
case NotificationLevel.Highlight:
|
||||
return _t("notifications|level_highlight");
|
||||
case NotificationLevel.Unsent:
|
||||
return _t("notifications|level_unsent");
|
||||
case NotificationLevel.Muted:
|
||||
return _t("notifications|level_muted");
|
||||
}
|
||||
}
|
||||
@@ -16,14 +16,14 @@ limitations under the License.
|
||||
|
||||
import { TypedEventEmitter } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { NotificationColor } from "./NotificationColor";
|
||||
import { NotificationLevel } from "./NotificationLevel";
|
||||
import { IDestroyable } from "../../utils/IDestroyable";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
|
||||
export interface INotificationStateSnapshotParams {
|
||||
symbol: string | null;
|
||||
count: number;
|
||||
color: NotificationColor;
|
||||
level: NotificationLevel;
|
||||
muted: boolean;
|
||||
knocked: boolean;
|
||||
}
|
||||
@@ -43,7 +43,7 @@ export abstract class NotificationState
|
||||
//
|
||||
protected _symbol: string | null = null;
|
||||
protected _count = 0;
|
||||
protected _color: NotificationColor = NotificationColor.None;
|
||||
protected _level: NotificationLevel = NotificationLevel.None;
|
||||
protected _muted = false;
|
||||
protected _knocked = false;
|
||||
|
||||
@@ -66,8 +66,8 @@ export abstract class NotificationState
|
||||
return this._count;
|
||||
}
|
||||
|
||||
public get color(): NotificationColor {
|
||||
return this._color;
|
||||
public get level(): NotificationLevel {
|
||||
return this._level;
|
||||
}
|
||||
|
||||
public get muted(): boolean {
|
||||
@@ -79,24 +79,24 @@ export abstract class NotificationState
|
||||
}
|
||||
|
||||
public get isIdle(): boolean {
|
||||
return this.color <= NotificationColor.None;
|
||||
return this.level <= NotificationLevel.None;
|
||||
}
|
||||
|
||||
public get isUnread(): boolean {
|
||||
if (this.color > NotificationColor.Bold) {
|
||||
if (this.level > NotificationLevel.Activity) {
|
||||
return true;
|
||||
} else {
|
||||
const hideBold = SettingsStore.getValue("feature_hidebold");
|
||||
return this.color === NotificationColor.Bold && !hideBold;
|
||||
return this.level === NotificationLevel.Activity && !hideBold;
|
||||
}
|
||||
}
|
||||
|
||||
public get hasUnreadCount(): boolean {
|
||||
return this.color >= NotificationColor.Grey && (!!this.count || !!this.symbol);
|
||||
return this.level >= NotificationLevel.Notification && (!!this.count || !!this.symbol);
|
||||
}
|
||||
|
||||
public get hasMentions(): boolean {
|
||||
return this.color >= NotificationColor.Red;
|
||||
return this.level >= NotificationLevel.Highlight;
|
||||
}
|
||||
|
||||
protected emitIfUpdated(snapshot: NotificationStateSnapshot): void {
|
||||
@@ -121,14 +121,14 @@ export abstract class NotificationState
|
||||
export class NotificationStateSnapshot {
|
||||
private readonly symbol: string | null;
|
||||
private readonly count: number;
|
||||
private readonly color: NotificationColor;
|
||||
private readonly level: NotificationLevel;
|
||||
private readonly muted: boolean;
|
||||
private readonly knocked: boolean;
|
||||
|
||||
public constructor(state: INotificationStateSnapshotParams) {
|
||||
this.symbol = state.symbol;
|
||||
this.count = state.count;
|
||||
this.color = state.color;
|
||||
this.level = state.level;
|
||||
this.muted = state.muted;
|
||||
this.knocked = state.knocked;
|
||||
}
|
||||
@@ -137,14 +137,14 @@ export class NotificationStateSnapshot {
|
||||
const before = {
|
||||
count: this.count,
|
||||
symbol: this.symbol,
|
||||
color: this.color,
|
||||
level: this.level,
|
||||
muted: this.muted,
|
||||
knocked: this.knocked,
|
||||
};
|
||||
const after = {
|
||||
count: other.count,
|
||||
symbol: other.symbol,
|
||||
color: other.color,
|
||||
level: other.level,
|
||||
muted: other.muted,
|
||||
knocked: other.knocked,
|
||||
};
|
||||
|
||||
@@ -90,11 +90,11 @@ export class RoomNotificationState extends NotificationState implements IDestroy
|
||||
private updateNotificationState(): void {
|
||||
const snapshot = this.snapshot();
|
||||
|
||||
const { color, symbol, count } = RoomNotifs.determineUnreadState(this.room);
|
||||
const { level, symbol, count } = RoomNotifs.determineUnreadState(this.room);
|
||||
const muted =
|
||||
RoomNotifs.getRoomNotifsState(this.room.client, this.room.roomId) === RoomNotifs.RoomNotifState.Mute;
|
||||
const knocked = SettingsStore.getValue("feature_ask_to_join") && this.room.getMyMembership() === "knock";
|
||||
this._color = color;
|
||||
this._level = level;
|
||||
this._symbol = symbol;
|
||||
this._count = count;
|
||||
this._muted = muted;
|
||||
|
||||
@@ -138,7 +138,7 @@ export class RoomNotificationStateStore extends AsyncStoreWithClient<IState> {
|
||||
if (
|
||||
this.globalState.symbol !== globalState.symbol ||
|
||||
this.globalState.count !== globalState.count ||
|
||||
this.globalState.color !== globalState.color ||
|
||||
this.globalState.level !== globalState.level ||
|
||||
this.globalState.numUnreadStates !== globalState.numUnreadStates ||
|
||||
forceEmit
|
||||
) {
|
||||
|
||||
@@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
import { Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { NotificationColor } from "./NotificationColor";
|
||||
import { NotificationLevel } from "./NotificationLevel";
|
||||
import { arrayDiff } from "../../utils/arrays";
|
||||
import { RoomNotificationState } from "./RoomNotificationState";
|
||||
import { NotificationState, NotificationStateEvents } from "./NotificationState";
|
||||
@@ -33,7 +33,7 @@ export class SpaceNotificationState extends NotificationState {
|
||||
}
|
||||
|
||||
public get symbol(): string | null {
|
||||
return this._color === NotificationColor.Unsent ? "!" : null;
|
||||
return this._level === NotificationLevel.Unsent ? "!" : null;
|
||||
}
|
||||
|
||||
public setRooms(rooms: Room[]): void {
|
||||
@@ -56,7 +56,7 @@ export class SpaceNotificationState extends NotificationState {
|
||||
}
|
||||
|
||||
public getFirstRoomWithNotifications(): string | undefined {
|
||||
return Object.values(this.states).find((state) => state.color >= this.color)?.room.roomId;
|
||||
return Object.values(this.states).find((state) => state.level >= this.level)?.room.roomId;
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
@@ -75,16 +75,16 @@ export class SpaceNotificationState extends NotificationState {
|
||||
const snapshot = this.snapshot();
|
||||
|
||||
this._count = 0;
|
||||
this._color = NotificationColor.None;
|
||||
this._level = NotificationLevel.None;
|
||||
for (const [roomId, state] of Object.entries(this.states)) {
|
||||
const room = this.rooms.find((r) => r.roomId === roomId);
|
||||
const roomTags = room ? RoomListStore.instance.getTagsForRoom(room) : [];
|
||||
|
||||
// We ignore unreads in LowPriority rooms, see https://github.com/vector-im/element-web/issues/16836
|
||||
if (roomTags.includes(DefaultTagID.LowPriority) && state.color === NotificationColor.Bold) continue;
|
||||
if (roomTags.includes(DefaultTagID.LowPriority) && state.level === NotificationLevel.Activity) continue;
|
||||
|
||||
this._count += state.count;
|
||||
this._color = Math.max(this.color, state.color);
|
||||
this._level = Math.max(this.level, state.level);
|
||||
}
|
||||
|
||||
// finally, publish an update if needed
|
||||
|
||||
@@ -14,24 +14,24 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { NotificationColor } from "./NotificationColor";
|
||||
import { NotificationLevel } from "./NotificationLevel";
|
||||
import { NotificationState } from "./NotificationState";
|
||||
|
||||
export class StaticNotificationState extends NotificationState {
|
||||
public static readonly RED_EXCLAMATION = StaticNotificationState.forSymbol("!", NotificationColor.Red);
|
||||
public static readonly RED_EXCLAMATION = StaticNotificationState.forSymbol("!", NotificationLevel.Highlight);
|
||||
|
||||
public constructor(symbol: string | null, count: number, color: NotificationColor) {
|
||||
public constructor(symbol: string | null, count: number, level: NotificationLevel) {
|
||||
super();
|
||||
this._symbol = symbol;
|
||||
this._count = count;
|
||||
this._color = color;
|
||||
this._level = level;
|
||||
}
|
||||
|
||||
public static forCount(count: number, color: NotificationColor): StaticNotificationState {
|
||||
return new StaticNotificationState(null, count, color);
|
||||
public static forCount(count: number, level: NotificationLevel): StaticNotificationState {
|
||||
return new StaticNotificationState(null, count, level);
|
||||
}
|
||||
|
||||
public static forSymbol(symbol: string, color: NotificationColor): StaticNotificationState {
|
||||
return new StaticNotificationState(symbol, 0, color);
|
||||
public static forSymbol(symbol: string, level: NotificationLevel): StaticNotificationState {
|
||||
return new StaticNotificationState(symbol, 0, level);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { NotificationColor } from "./NotificationColor";
|
||||
import { NotificationLevel } from "./NotificationLevel";
|
||||
import { NotificationState } from "./NotificationState";
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ export class SummarizedNotificationState extends NotificationState {
|
||||
super();
|
||||
this._symbol = null;
|
||||
this._count = 0;
|
||||
this._color = NotificationColor.None;
|
||||
this._level = NotificationLevel.None;
|
||||
}
|
||||
|
||||
public get numUnreadStates(): number {
|
||||
@@ -52,8 +52,8 @@ export class SummarizedNotificationState extends NotificationState {
|
||||
if (other.count) {
|
||||
this._count += other.count;
|
||||
}
|
||||
if (other.color > this.color) {
|
||||
this._color = other.color;
|
||||
if (other.level > this.level) {
|
||||
this._level = other.level;
|
||||
}
|
||||
if (other.hasUnreadCount) {
|
||||
this.totalStatesWithUnread++;
|
||||
|
||||
@@ -22,27 +22,27 @@ import { RoomUpdateCause, TagID } from "../../models";
|
||||
import { SortAlgorithm } from "../models";
|
||||
import { sortRoomsWithAlgorithm } from "../tag-sorting";
|
||||
import { OrderingAlgorithm } from "./OrderingAlgorithm";
|
||||
import { NotificationColor } from "../../../notifications/NotificationColor";
|
||||
import { NotificationLevel } from "../../../notifications/NotificationLevel";
|
||||
import { RoomNotificationStateStore } from "../../../notifications/RoomNotificationStateStore";
|
||||
|
||||
type CategorizedRoomMap = {
|
||||
[category in NotificationColor]: Room[];
|
||||
[category in NotificationLevel]: Room[];
|
||||
};
|
||||
|
||||
type CategoryIndex = Partial<{
|
||||
[category in NotificationColor]: number; // integer
|
||||
[category in NotificationLevel]: number; // integer
|
||||
}>;
|
||||
|
||||
// Caution: changing this means you'll need to update a bunch of assumptions and
|
||||
// comments! Check the usage of Category carefully to figure out what needs changing
|
||||
// if you're going to change this array's order.
|
||||
const CATEGORY_ORDER = [
|
||||
NotificationColor.Unsent,
|
||||
NotificationColor.Red,
|
||||
NotificationColor.Grey,
|
||||
NotificationColor.Bold,
|
||||
NotificationColor.None, // idle
|
||||
NotificationColor.Muted,
|
||||
NotificationLevel.Unsent,
|
||||
NotificationLevel.Highlight,
|
||||
NotificationLevel.Notification,
|
||||
NotificationLevel.Activity,
|
||||
NotificationLevel.None, // idle
|
||||
NotificationLevel.Muted,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -77,12 +77,12 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||
// noinspection JSMethodCanBeStatic
|
||||
private categorizeRooms(rooms: Room[]): CategorizedRoomMap {
|
||||
const map: CategorizedRoomMap = {
|
||||
[NotificationColor.Unsent]: [],
|
||||
[NotificationColor.Red]: [],
|
||||
[NotificationColor.Grey]: [],
|
||||
[NotificationColor.Bold]: [],
|
||||
[NotificationColor.None]: [],
|
||||
[NotificationColor.Muted]: [],
|
||||
[NotificationLevel.Unsent]: [],
|
||||
[NotificationLevel.Highlight]: [],
|
||||
[NotificationLevel.Notification]: [],
|
||||
[NotificationLevel.Activity]: [],
|
||||
[NotificationLevel.None]: [],
|
||||
[NotificationLevel.Muted]: [],
|
||||
};
|
||||
for (const room of rooms) {
|
||||
const category = this.getRoomCategory(room);
|
||||
@@ -92,11 +92,11 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||
}
|
||||
|
||||
// noinspection JSMethodCanBeStatic
|
||||
private getRoomCategory(room: Room): NotificationColor {
|
||||
private getRoomCategory(room: Room): NotificationLevel {
|
||||
// It's fine for us to call this a lot because it's cached, and we shouldn't be
|
||||
// wasting anything by doing so as the store holds single references
|
||||
const state = RoomNotificationStateStore.instance.getRoomState(room);
|
||||
return this.isMutedToBottom && state.muted ? NotificationColor.Muted : state.color;
|
||||
return this.isMutedToBottom && state.muted ? NotificationLevel.Muted : state.level;
|
||||
}
|
||||
|
||||
public setRooms(rooms: Room[]): void {
|
||||
@@ -106,7 +106,7 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||
// Every other sorting type affects the categories, not the whole tag.
|
||||
const categorized = this.categorizeRooms(rooms);
|
||||
for (const category of Object.keys(categorized)) {
|
||||
const notificationColor = category as unknown as NotificationColor;
|
||||
const notificationColor = category as unknown as NotificationLevel;
|
||||
const roomsToOrder = categorized[notificationColor];
|
||||
categorized[notificationColor] = sortRoomsWithAlgorithm(
|
||||
roomsToOrder,
|
||||
@@ -128,7 +128,7 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
private getCategoryIndex(category: NotificationColor): number {
|
||||
private getCategoryIndex(category: NotificationLevel): number {
|
||||
const categoryIndex = this.indices[category];
|
||||
|
||||
if (categoryIndex === undefined) {
|
||||
@@ -213,7 +213,7 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||
return true; // change made
|
||||
}
|
||||
|
||||
private sortCategory(category: NotificationColor): void {
|
||||
private sortCategory(category: NotificationLevel): void {
|
||||
// This should be relatively quick because the room is usually inserted at the top of the
|
||||
// category, and most popular sorting algorithms will deal with trying to keep the active
|
||||
// room at the top/start of the category. For the few algorithms that will have to move the
|
||||
@@ -231,7 +231,7 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||
}
|
||||
|
||||
// noinspection JSMethodCanBeStatic
|
||||
private getCategoryFromIndices(index: number, indices: CategoryIndex): NotificationColor {
|
||||
private getCategoryFromIndices(index: number, indices: CategoryIndex): NotificationLevel {
|
||||
for (let i = 0; i < CATEGORY_ORDER.length; i++) {
|
||||
const category = CATEGORY_ORDER[i];
|
||||
const isLast = i === CATEGORY_ORDER.length - 1;
|
||||
@@ -252,8 +252,8 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||
// noinspection JSMethodCanBeStatic
|
||||
private moveRoomIndexes(
|
||||
nRooms: number,
|
||||
fromCategory: NotificationColor,
|
||||
toCategory: NotificationColor,
|
||||
fromCategory: NotificationLevel,
|
||||
toCategory: NotificationLevel,
|
||||
indices: CategoryIndex,
|
||||
): void {
|
||||
// We have to update the index of the category *after* the from/toCategory variables
|
||||
@@ -266,7 +266,7 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||
this.alterCategoryPositionBy(toCategory, +nRooms, indices);
|
||||
}
|
||||
|
||||
private alterCategoryPositionBy(category: NotificationColor, n: number, indices: CategoryIndex): void {
|
||||
private alterCategoryPositionBy(category: NotificationLevel, n: number, indices: CategoryIndex): void {
|
||||
// Note: when we alter a category's index, we actually have to modify the ones following
|
||||
// the target and not the target itself.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user