stoat-for-desktop/components/state/stores/Ordering.ts

107 lines
2.1 KiB
TypeScript

import { Client } from "stoat.js";
import { State } from "..";
import { AbstractStore } from ".";
export interface TypeOrdering {
/**
* Ordered list of server IDs
*/
servers: string[];
}
/**
* Handles ordering of items in the app interface.
*/
export class Ordering extends AbstractStore<"ordering", TypeOrdering> {
/**
* Construct store
* @param state State
*/
constructor(state: State) {
super(state, "ordering");
this.setServerOrder = this.setServerOrder.bind(this);
}
/**
* Hydrate external context
*/
hydrate(): void {
/** nothing needs to be done */
}
/**
* Generate default values
*/
default(): TypeOrdering {
return {
servers: [],
};
}
/**
* Validate the given data to see if it is compliant and return a compliant object
*/
clean(input: Partial<TypeOrdering>): TypeOrdering {
const ordering: TypeOrdering = this.default();
if (Array.isArray(input.servers)) {
for (const serverId of input.servers) {
if (typeof serverId === "string") {
ordering.servers.push(serverId);
}
}
}
return ordering;
}
/**
* All known servers with ordering applied
* @returns List of Server objects
*/
orderedServers(client: Client) {
const known = new Set(client?.servers.keys() ?? []);
const ordered = [...this.get().servers];
const out = [];
for (const id of ordered) {
if (known.delete(id)) {
out.push(client!.servers.get(id)!);
}
}
for (const id of known) {
out.push(client!.servers.get(id)!);
}
return out;
}
/**
* Set server ordering
* @param ids List of IDs
*/
setServerOrder(ids: string[]) {
this.set("servers", ids);
}
/**
* All known active DM conversations ordered by last updated
* @returns List of Channel objects
*/
orderedConversations(client: Client) {
return (
client.channels
.toList()
.filter(
(channel) =>
(channel.type === "DirectMessage" && channel.active) ||
channel.type === "Group",
)
.sort((a, b) => +b.updatedAt - +a.updatedAt) ?? []
);
}
}