mirror of
https://github.com/spacebarchat/client.git
synced 2024-11-21 18:02:32 +01:00
mark channel as read on open
This commit is contained in:
parent
329a14ccf5
commit
2f6a56d65e
@ -4,13 +4,13 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { ContextMenuContext } from "../../contexts/ContextMenuContext";
|
import { ContextMenuContext } from "../../contexts/ContextMenuContext";
|
||||||
import { modalController } from "../../controllers/modals";
|
import { modalController } from "../../controllers/modals";
|
||||||
|
import { useAppStore } from "../../hooks/useAppStore";
|
||||||
import Channel from "../../stores/objects/Channel";
|
import Channel from "../../stores/objects/Channel";
|
||||||
import { Permissions } from "../../utils/Permissions";
|
import { Permissions } from "../../utils/Permissions";
|
||||||
import Icon from "../Icon";
|
import Icon from "../Icon";
|
||||||
import SidebarPill from "../SidebarPill";
|
import SidebarPill from "../SidebarPill";
|
||||||
import Floating from "../floating/Floating";
|
import Floating from "../floating/Floating";
|
||||||
import FloatingTrigger from "../floating/FloatingTrigger";
|
import FloatingTrigger from "../floating/FloatingTrigger";
|
||||||
import { useAppStore } from "../../hooks/useAppStore";
|
|
||||||
|
|
||||||
const ListItem = styled.div<{ isCategory?: boolean }>`
|
const ListItem = styled.div<{ isCategory?: boolean }>`
|
||||||
padding: ${(props) => (props.isCategory ? "16px 8px 0 0" : "1px 8px 0 0")};
|
padding: ${(props) => (props.isCategory ? "16px 8px 0 0" : "1px 8px 0 0")};
|
||||||
@ -90,7 +90,7 @@ function ChannelListItem({ channel, isCategory, active }: Props) {
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SidebarPill type={channel.hasUnread() ? "unread" : "none"} />
|
<SidebarPill type={channel.unread ? "unread" : "none"} />
|
||||||
{channel.channelIcon && !isCategory && (
|
{channel.channelIcon && !isCategory && (
|
||||||
<Icon
|
<Icon
|
||||||
icon={channel.channelIcon}
|
icon={channel.channelIcon}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { runInAction } from "mobx";
|
import { runInAction } from "mobx";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import React from "react";
|
import React, { useEffect } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { useAppStore } from "../../hooks/useAppStore";
|
import { useAppStore } from "../../hooks/useAppStore";
|
||||||
import useLogger from "../../hooks/useLogger";
|
import useLogger from "../../hooks/useLogger";
|
||||||
@ -57,6 +57,10 @@ function ChatContent({ channel, guild }: Props2) {
|
|||||||
const app = useAppStore();
|
const app = useAppStore();
|
||||||
const readstate = app.readStateStore.get(channel.id);
|
const readstate = app.readStateStore.get(channel.id);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
channel.markAsRead();
|
||||||
|
}, [channel, guild]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<MessageList guild={guild} channel={channel} before={readstate?.lastMessageId} />
|
<MessageList guild={guild} channel={channel} before={readstate?.lastMessageId} />
|
||||||
|
@ -143,6 +143,8 @@ export default class GatewayConnectionStore {
|
|||||||
this.dispatchHandlers.set(GatewayDispatchEvents.ChannelCreate, this.onChannelCreate);
|
this.dispatchHandlers.set(GatewayDispatchEvents.ChannelCreate, this.onChannelCreate);
|
||||||
this.dispatchHandlers.set(GatewayDispatchEvents.ChannelUpdate, this.onChannelUpdate);
|
this.dispatchHandlers.set(GatewayDispatchEvents.ChannelUpdate, this.onChannelUpdate);
|
||||||
this.dispatchHandlers.set(GatewayDispatchEvents.ChannelDelete, this.onChannelDelete);
|
this.dispatchHandlers.set(GatewayDispatchEvents.ChannelDelete, this.onChannelDelete);
|
||||||
|
// @ts-expect-error missing event in typings
|
||||||
|
this.dispatchHandlers.set("MESSAGE_ACK", this.onMessageAck);
|
||||||
|
|
||||||
this.dispatchHandlers.set(GatewayDispatchEvents.MessageCreate, this.onMessageCreate);
|
this.dispatchHandlers.set(GatewayDispatchEvents.MessageCreate, this.onMessageCreate);
|
||||||
this.dispatchHandlers.set(GatewayDispatchEvents.MessageUpdate, this.onMessageUpdate);
|
this.dispatchHandlers.set(GatewayDispatchEvents.MessageUpdate, this.onMessageUpdate);
|
||||||
@ -633,6 +635,23 @@ export default class GatewayConnectionStore {
|
|||||||
guild.removeChannel(data.id);
|
guild.removeChannel(data.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onMessageAck = (data: { channel_id: string; message_id: string; version: number }) => {
|
||||||
|
// get readstate for channel
|
||||||
|
const readstate = this.app.readStateStore.get(data.channel_id);
|
||||||
|
if (!readstate) {
|
||||||
|
this.logger.warn(`[MessageAck] Readstate not found for channel ${data.channel_id}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
runInAction(() => {
|
||||||
|
readstate.lastMessageId = data.message_id;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.logger.debug(
|
||||||
|
`[MessageAck] Updated last message id for channel readstate ${data.channel_id} to ${data.message_id}`,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
private onMessageCreate = (data: GatewayMessageCreateDispatchData) => {
|
private onMessageCreate = (data: GatewayMessageCreateDispatchData) => {
|
||||||
const guild = this.app.guilds.get(data.guild_id!);
|
const guild = this.app.guilds.get(data.guild_id!);
|
||||||
if (!guild) {
|
if (!guild) {
|
||||||
|
@ -311,7 +311,8 @@ export default class Channel {
|
|||||||
return listId;
|
return listId;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasUnread() {
|
@computed
|
||||||
|
get unread() {
|
||||||
const readState = this.app.readStateStore.get(this.id);
|
const readState = this.app.readStateStore.get(this.id);
|
||||||
if (!readState) {
|
if (!readState) {
|
||||||
// this.logger.warn(`Failed to find readstate for channel ${this.id}`); // this just causes unnecessary spam
|
// this.logger.warn(`Failed to find readstate for channel ${this.id}`); // this just causes unnecessary spam
|
||||||
@ -320,4 +321,23 @@ export default class Channel {
|
|||||||
|
|
||||||
return readState.lastMessageId !== this.lastMessageId;
|
return readState.lastMessageId !== this.lastMessageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
markAsRead() {
|
||||||
|
const readState = this.app.readStateStore.get(this.id);
|
||||||
|
if (!readState) {
|
||||||
|
this.logger.warn(`Failed to find readstate for channel ${this.id}`); // this just causes unnecessary spam
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.app.rest
|
||||||
|
.post(Routes.channelMessage(this.id, readState.lastMessageId) + "/ack", {
|
||||||
|
mention_count: readState.mentionCount,
|
||||||
|
})
|
||||||
|
.then((r) => {
|
||||||
|
this.logger.debug(`Acked ${this.lastMessageId} for channel ${this.id}`, r);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
this.logger.error(`Failed to ack ${this.lastMessageId} for channel ${this.id}`, e);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import type { APIReadState } from "@spacebarchat/spacebar-api-types/v9";
|
import { type APIReadState } from "@spacebarchat/spacebar-api-types/v9";
|
||||||
import { action, observable } from "mobx";
|
import { action, observable } from "mobx";
|
||||||
|
import Logger from "../../utils/Logger";
|
||||||
import AppStore from "../AppStore";
|
import AppStore from "../AppStore";
|
||||||
|
|
||||||
export default class ReadState {
|
export default class ReadState {
|
||||||
|
private readonly logger: Logger;
|
||||||
private readonly app: AppStore;
|
private readonly app: AppStore;
|
||||||
|
|
||||||
id: string;
|
id: string;
|
||||||
@ -11,9 +13,10 @@ export default class ReadState {
|
|||||||
@observable mentionCount: number | null;
|
@observable mentionCount: number | null;
|
||||||
|
|
||||||
constructor(app: AppStore, data: APIReadState) {
|
constructor(app: AppStore, data: APIReadState) {
|
||||||
|
this.logger = new Logger("ReadState");
|
||||||
this.app = app;
|
this.app = app;
|
||||||
|
|
||||||
this.id = data.id;
|
this.id = data.id; // channel id
|
||||||
this.lastMessageId = data.last_message_id;
|
this.lastMessageId = data.last_message_id;
|
||||||
this.lastPinTimestamp = data.last_pin_timestamp;
|
this.lastPinTimestamp = data.last_pin_timestamp;
|
||||||
this.mentionCount = data.mention_count;
|
this.mentionCount = data.mention_count;
|
||||||
|
Loading…
Reference in New Issue
Block a user