1
0
mirror of https://github.com/spacebarchat/client.git synced 2024-11-25 11:42:30 +01:00

rewrite presence store

This commit is contained in:
Puyodead1 2023-12-09 20:31:05 -05:00
parent 876b09b878
commit ce230709e4
No known key found for this signature in database
GPG Key ID: A4FA4FEC0DD353FC
4 changed files with 99 additions and 64 deletions

View File

@ -2,6 +2,7 @@ import {
APIGuildMember, APIGuildMember,
APIMessage, APIMessage,
ChannelType, ChannelType,
GatewayActivity,
GatewayChannelCreateDispatchData, GatewayChannelCreateDispatchData,
GatewayChannelDeleteDispatchData, GatewayChannelDeleteDispatchData,
GatewayChannelUpdateDispatchData, GatewayChannelUpdateDispatchData,
@ -42,10 +43,23 @@ const GATEWAY_VERSION = "9";
const GATEWAY_ENCODING = "json"; const GATEWAY_ENCODING = "json";
const RECONNECT_TIMEOUT = 10000; // start at 10 seconds, doubles each time const RECONNECT_TIMEOUT = 10000; // start at 10 seconds, doubles each time
interface GatewaySession {
active: boolean;
activities: GatewayActivity[];
client_info: {
client?: string;
os?: string;
version?: number;
};
session_id: string;
status: PresenceUpdateStatus;
}
export default class GatewayConnectionStore { export default class GatewayConnectionStore {
private readonly logger: Logger = new Logger("GatewayConnectionStore"); private readonly logger: Logger = new Logger("GatewayConnectionStore");
@observable private socket: WebSocket | null = null; @observable private socket: WebSocket | null = null;
@observable private sessionId: string | null = null; @observable public sessionId: string | null = null;
@observable public session: GatewaySession | undefined;
@observable public readyState: number = WebSocket.CLOSED; @observable public readyState: number = WebSocket.CLOSED;
private app: AppStore; private app: AppStore;
@ -67,6 +81,7 @@ export default class GatewayConnectionStore {
makeObservable(this); makeObservable(this);
} }
/** /**
* Starts connection to gateway * Starts connection to gateway
*/ */
@ -449,8 +464,9 @@ export default class GatewayConnectionStore {
*/ */
private onReady = (data: GatewayReadyDispatchData) => { private onReady = (data: GatewayReadyDispatchData) => {
this.logger.info(`[Ready] took ${Date.now() - this.connectionStartTime!}ms`); this.logger.info(`[Ready] took ${Date.now() - this.connectionStartTime!}ms`);
const { session_id, guilds, users, user, private_channels } = data; const { session_id, guilds, users, user, private_channels, sessions } = data;
this.sessionId = session_id; this.sessionId = session_id;
this.session = (sessions as GatewaySession[]).find((x) => x.session_id === session_id);
this.app.setUser(user); this.app.setUser(user);
@ -665,7 +681,7 @@ export default class GatewayConnectionStore {
}; };
private onPresenceUpdate = (data: GatewayPresenceUpdateDispatchData) => { private onPresenceUpdate = (data: GatewayPresenceUpdateDispatchData) => {
this.app.presences.add(data); this.app.presences.update(data);
}; };
private onTypingStart = (data: GatewayTypingStartDispatchData) => { private onTypingStart = (data: GatewayTypingStartDispatchData) => {

View File

@ -63,6 +63,12 @@ export default class GuildMemberListStore {
data: [], data: [],
}); });
} else { } else {
// handle presence
this.app.presences.add({
...item.member.presence,
guild_id: this.guild.id,
});
const member = this.guild.members.get(item.member.id); const member = this.guild.members.get(item.member.id);
if (member) { if (member) {
listData[listData.length - 1].data.push({ listData[listData.length - 1].data.push({

View File

@ -1,29 +1,11 @@
import { import type { GatewayPresenceUpdateDispatchData, Snowflake } from "@spacebarchat/spacebar-api-types/v9";
GatewayActivity, import { ObservableMap, action, computed, makeObservable, observable } from "mobx";
GatewayGuildMemberListUpdateMember,
GatewayPresenceClientStatus,
GatewayPresenceUpdate,
PresenceUpdateStatus,
Snowflake,
} from "@spacebarchat/spacebar-api-types/v9";
import { action, makeObservable, observable } from "mobx";
import { OneKeyFrom } from "../utils/interfaces/common";
import AppStore from "./AppStore"; import AppStore from "./AppStore";
import Presence from "./objects/Presence";
export default class PresenceStore { export default class PresenceStore {
private readonly app: AppStore; private readonly app: AppStore;
@observable presences = observable.map<Snowflake, PresenceUpdateStatus>(); @observable presences = observable.map<Snowflake, ObservableMap<Snowflake, Presence>>();
@observable presencesForGuilds = observable.map<
Snowflake,
Map<
Snowflake,
Pick<GatewayPresenceUpdate, "activities" | "client_status" | "status"> & {
timestamp: number;
}
>
>();
@observable activities = observable.map<Snowflake, GatewayActivity[]>();
@observable clientStatuses = observable.map<Snowflake, OneKeyFrom<GatewayPresenceClientStatus>>();
constructor(app: AppStore) { constructor(app: AppStore) {
this.app = app; this.app = app;
@ -32,50 +14,45 @@ export default class PresenceStore {
} }
@action @action
add(presence: GatewayPresenceUpdate | GatewayGuildMemberListUpdateMember["presence"]) { add(data: GatewayPresenceUpdateDispatchData) {
if (presence.status) { if (!this.presences.has(data.guild_id)) {
this.presences.set(presence.user.id, presence.status); this.presences.set(data.guild_id, observable.map<Snowflake, Presence>());
} }
if (presence.activities) { this.presences.get(data.guild_id)?.set(data.user.id, new Presence(this.app, data));
this.activities.set(presence.user.id, presence.activities);
}
if ("client_status" in presence) {
this.clientStatuses.set(
presence.user.id,
presence.client_status as OneKeyFrom<GatewayPresenceClientStatus>,
);
}
if ("guild_id" in presence) {
const guild = this.presencesForGuilds.get(presence.guild_id);
if (guild) {
guild.set(presence.user.id, {
activities: presence.activities,
client_status: presence.client_status,
status: presence.status,
timestamp: Date.now(),
});
}
}
} }
// static getStatusColor(status: PresenceUpdateStatus) { @action
// const theme = addAll(data: GatewayPresenceUpdateDispatchData[]) {
data.forEach((p) => this.add(p));
}
// switch (status) { @computed
// case 'online': get all() {
// return theme.colors.palette.green80; return Array.from(this.presences.values());
// case 'idle': }
// return theme.colors.palette.yellow80;
// case 'dnd': @action
// return theme.colors.palette.red80; remove(id: Snowflake) {
// case 'offline': this.presences.delete(id);
// case 'invisible': }
// return theme.colors.palette.gray80;
// } @action
// } update(data: GatewayPresenceUpdateDispatchData) {
this.presences.get(data.guild_id)?.get(data.user.id)?.update(data);
}
get(id: Snowflake) {
return this.presences.get(id);
}
has(id: Snowflake) {
return this.presences.has(id);
}
asList() {
return Array.from(this.presences.values());
}
get size() { get size() {
return this.presences.size; return this.presences.size;

View File

@ -0,0 +1,36 @@
import type {
APIUser,
GatewayActivity,
GatewayPresenceClientStatus,
GatewayPresenceUpdateDispatchData,
PresenceUpdateStatus,
Snowflake,
} from "@spacebarchat/spacebar-api-types/v9";
import { action, observable } from "mobx";
import AppStore from "../AppStore";
import User from "./User";
export default class Presence {
private readonly app: AppStore;
@observable public readonly user: User;
@observable public readonly guildId?: Snowflake;
@observable public readonly status: PresenceUpdateStatus | undefined;
@observable public readonly activities: GatewayActivity[] | undefined;
@observable public readonly clientStatus: GatewayPresenceClientStatus | undefined;
constructor(app: AppStore, data: GatewayPresenceUpdateDispatchData) {
this.app = app;
this.user = this.app.users.get(data.user.id) ?? new User(data.user as APIUser); // TODO: is this right?
this.guildId = data.guild_id;
this.status = data.status;
this.activities = data.activities;
this.clientStatus = data.client_status;
}
@action
update(data: GatewayPresenceUpdateDispatchData) {
Object.assign(this, data);
}
}