mirror of
https://github.com/spacebarchat/client.git
synced 2024-11-22 10:22:30 +01:00
fix upload progress
This commit is contained in:
parent
3bf5f11f78
commit
b1a6f318be
@ -1,6 +1,7 @@
|
||||
import { observer } from "mobx-react-lite";
|
||||
import styled from "styled-components";
|
||||
import { QueuedMessage } from "../../stores/MessageQueue";
|
||||
import { useAppStore } from "../../stores/AppStore";
|
||||
import QueuedMessage from "../../stores/objects/QueuedMessage";
|
||||
import Icon from "../Icon";
|
||||
import IconButton from "../IconButton";
|
||||
|
||||
@ -41,7 +42,7 @@ interface Props {
|
||||
}
|
||||
|
||||
function AttachmentUploadProgress({ message }: Props) {
|
||||
console.log(message.progress);
|
||||
const app = useAppStore();
|
||||
|
||||
return (
|
||||
<Container>
|
||||
@ -49,7 +50,14 @@ function AttachmentUploadProgress({ message }: Props) {
|
||||
<div>{message.files!.length === 1 ? message.files![0].name : `${message.files!.length} files`}</div>
|
||||
<Progress value={message.progress} max={100} />
|
||||
</Wrapper>
|
||||
<IconButton variant="blank">
|
||||
<IconButton
|
||||
variant="blank"
|
||||
onClick={() => {
|
||||
message.abort();
|
||||
// remove the message from the queue
|
||||
app.queue.remove(message.id);
|
||||
}}
|
||||
>
|
||||
<CustomIcon icon="mdiClose" size="24px" />
|
||||
</IconButton>
|
||||
</Container>
|
||||
|
@ -6,8 +6,8 @@ import Moment from "react-moment";
|
||||
import styled from "styled-components";
|
||||
import { ContextMenuContext } from "../../contexts/ContextMenuContext";
|
||||
import useLogger from "../../hooks/useLogger";
|
||||
import { QueuedMessage } from "../../stores/MessageQueue";
|
||||
import { default as MessageObject } from "../../stores/objects/Message";
|
||||
import QueuedMessage from "../../stores/objects/QueuedMessage";
|
||||
import { calculateImageRatio, calculateScaledDimensions } from "../../utils/Message";
|
||||
import { calendarStrings } from "../../utils/i18n";
|
||||
import Avatar from "../Avatar";
|
||||
@ -183,8 +183,6 @@ function Message({ message, isHeader, isSending, isFailed }: Props) {
|
||||
);
|
||||
}, []);
|
||||
|
||||
if (message instanceof QueuedMessage) console.log(`progress at msg`, message.progress);
|
||||
|
||||
// construct the context menu options
|
||||
// React.useEffect(() => {
|
||||
// // if the message is queued, we don't need a context menu
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { observer } from "mobx-react-lite";
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { QueuedMessage, QueuedMessageStatus } from "../../stores/MessageQueue";
|
||||
import { QueuedMessageStatus } from "../../stores/MessageQueue";
|
||||
import { default as MessageObject } from "../../stores/objects/Message";
|
||||
import QueuedMessage from "../../stores/objects/QueuedMessage";
|
||||
import Message from "./Message";
|
||||
|
||||
const Container = styled.div`
|
||||
@ -18,7 +19,6 @@ interface Props {
|
||||
*/
|
||||
function MessageGroup({ messages }: Props) {
|
||||
const renderMessage = React.useCallback((message: MessageObject | QueuedMessage, index: number) => {
|
||||
if (message instanceof QueuedMessage) console.log(`progress at msg group`, message.progress);
|
||||
return (
|
||||
<Message
|
||||
key={message.id}
|
||||
|
@ -123,7 +123,6 @@ function MessageInput(props: Props) {
|
||||
const shouldSend = !app.experiments.isTreatmentEnabled("message_queue", 1);
|
||||
|
||||
const canSend = props.channel.canSendMessage(content, attachments);
|
||||
console.log(`canSendMessage`, canSend);
|
||||
if (!canSend && !shouldFail) return;
|
||||
|
||||
const nonce = Snowflake.generate();
|
||||
@ -147,8 +146,8 @@ function MessageInput(props: Props) {
|
||||
} else {
|
||||
body = { content, nonce };
|
||||
}
|
||||
props.channel.sendMessage(body, msg.progressCallback).catch((error) => {
|
||||
app.queue.error(nonce, error as string);
|
||||
props.channel.sendMessage(body, msg).catch((error) => {
|
||||
if (error) app.queue.error(nonce, error as string);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -5,10 +5,10 @@ import PulseLoader from "react-spinners/PulseLoader";
|
||||
import styled from "styled-components";
|
||||
import useLogger from "../../hooks/useLogger";
|
||||
import { useAppStore } from "../../stores/AppStore";
|
||||
import { QueuedMessage } from "../../stores/MessageQueue";
|
||||
import Channel from "../../stores/objects/Channel";
|
||||
import Guild from "../../stores/objects/Guild";
|
||||
import Message from "../../stores/objects/Message";
|
||||
import QueuedMessage from "../../stores/objects/QueuedMessage";
|
||||
import { Permissions } from "../../utils/Permissions";
|
||||
import { HorizontalDivider } from "../Divider";
|
||||
import MessageGroup from "./MessageGroup";
|
||||
@ -66,6 +66,7 @@ function MessageList({ guild, channel }: Props) {
|
||||
|
||||
// get last group
|
||||
const lastGroup = channel.messages.grouped[channel.messages.grouped.length - 1];
|
||||
// ignore queued messages
|
||||
if ("status" in lastGroup) return;
|
||||
// get first message in the group to use as before
|
||||
const before = lastGroup[0].id;
|
||||
@ -112,7 +113,9 @@ function MessageList({ guild, channel }: Props) {
|
||||
</EndMessageContainer>
|
||||
}
|
||||
>
|
||||
{channel.messages.grouped.map((group, index) => renderMessageGroup(group, index))}
|
||||
{channel.messages.grouped.map((group, index) => (
|
||||
<MessageGroup key={index} messages={group} />
|
||||
))}
|
||||
</InfiniteScroll>
|
||||
) : (
|
||||
<div
|
||||
|
@ -1,9 +1,9 @@
|
||||
import type { APIMessage } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import { MessageType } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import { action, computed, makeAutoObservable, observable } from "mobx";
|
||||
|
||||
import type { IObservableArray } from "mobx";
|
||||
import Snowflake from "../utils/Snowflake";
|
||||
import QueuedMessage from "./objects/QueuedMessage";
|
||||
import User from "./objects/User";
|
||||
|
||||
export enum QueuedMessageStatus {
|
||||
@ -19,46 +19,6 @@ export type QueuedMessageData = {
|
||||
files?: File[];
|
||||
};
|
||||
|
||||
// export interface QueuedMessage extends QueuedMessageData {
|
||||
// status: QueuedMessageStatus;
|
||||
// error?: string;
|
||||
// timestamp: Date;
|
||||
// type: MessageType;
|
||||
// }
|
||||
|
||||
export class QueuedMessage implements QueuedMessageData {
|
||||
id: string;
|
||||
channel: string;
|
||||
author: User;
|
||||
content: string;
|
||||
files?: File[];
|
||||
@observable progress: number;
|
||||
status: QueuedMessageStatus;
|
||||
error?: string;
|
||||
timestamp: Date;
|
||||
type: MessageType;
|
||||
|
||||
constructor(data: QueuedMessageData) {
|
||||
this.id = data.id;
|
||||
this.channel = data.channel;
|
||||
this.author = data.author;
|
||||
this.content = data.content;
|
||||
this.files = data.files;
|
||||
this.progress = 0;
|
||||
this.status = QueuedMessageStatus.SENDING;
|
||||
this.timestamp = new Date();
|
||||
this.type = MessageType.Default;
|
||||
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
@action
|
||||
progressCallback(e: ProgressEvent) {
|
||||
this.progress = Math.round((e.loaded / e.total) * 100);
|
||||
console.log(this.progress);
|
||||
}
|
||||
}
|
||||
|
||||
export default class MessageQueue {
|
||||
@observable private readonly messages: IObservableArray<QueuedMessage>;
|
||||
|
||||
|
@ -4,8 +4,8 @@ import { action, computed, makeObservable, observable } from "mobx";
|
||||
import useLogger from "../hooks/useLogger";
|
||||
import Logger from "../utils/Logger";
|
||||
import AppStore from "./AppStore";
|
||||
import { QueuedMessage } from "./MessageQueue";
|
||||
import Message from "./objects/Message";
|
||||
import QueuedMessage from "./objects/QueuedMessage";
|
||||
|
||||
export default class MessageStore {
|
||||
private readonly app: AppStore;
|
||||
|
@ -19,6 +19,7 @@ import Logger from "../../utils/Logger";
|
||||
import { APIError } from "../../utils/interfaces/api";
|
||||
import AppStore from "../AppStore";
|
||||
import MessageStore from "../MessageStore";
|
||||
import QueuedMessage from "./QueuedMessage";
|
||||
|
||||
export default class Channel {
|
||||
private readonly logger: Logger = new Logger("Channel");
|
||||
@ -198,13 +199,13 @@ export default class Channel {
|
||||
}
|
||||
|
||||
@action
|
||||
async sendMessage(data: RESTPostAPIChannelMessageJSONBody | FormData, cb?: (e: ProgressEvent) => void) {
|
||||
async sendMessage(data: RESTPostAPIChannelMessageJSONBody | FormData, msg?: QueuedMessage) {
|
||||
if (data instanceof FormData)
|
||||
return this.app.rest.postFormData<RESTPostAPIChannelMessageResult>(
|
||||
Routes.channelMessages(this.id),
|
||||
data,
|
||||
undefined,
|
||||
cb,
|
||||
msg,
|
||||
);
|
||||
return this.app.rest.post<RESTPostAPIChannelMessageJSONBody, RESTPostAPIChannelMessageResult>(
|
||||
Routes.channelMessages(this.id),
|
||||
|
46
src/stores/objects/QueuedMessage.ts
Normal file
46
src/stores/objects/QueuedMessage.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { MessageType } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import { action, makeAutoObservable, observable } from "mobx";
|
||||
import { QueuedMessageData, QueuedMessageStatus } from "../MessageQueue";
|
||||
import User from "./User";
|
||||
|
||||
export default class QueuedMessage {
|
||||
id: string;
|
||||
channel: string;
|
||||
author: User;
|
||||
content: string;
|
||||
files?: File[];
|
||||
@observable progress = 0;
|
||||
status: QueuedMessageStatus;
|
||||
error?: string;
|
||||
timestamp: Date;
|
||||
type: MessageType;
|
||||
abortCallback?: () => void;
|
||||
|
||||
constructor(data: QueuedMessageData) {
|
||||
this.id = data.id;
|
||||
this.channel = data.channel;
|
||||
this.author = data.author;
|
||||
this.content = data.content;
|
||||
this.files = data.files;
|
||||
this.status = QueuedMessageStatus.SENDING;
|
||||
this.timestamp = new Date();
|
||||
this.type = MessageType.Default;
|
||||
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
@action
|
||||
updateProgress(e: ProgressEvent) {
|
||||
this.progress = Math.round((e.loaded / e.total) * 100);
|
||||
}
|
||||
|
||||
setAbortCallback(cb: () => void) {
|
||||
this.abortCallback = cb;
|
||||
}
|
||||
|
||||
abort() {
|
||||
if (this.abortCallback) {
|
||||
this.abortCallback();
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
// import {DomainStore} from '../stores/DomainStore';
|
||||
|
||||
import AppStore from "../stores/AppStore";
|
||||
import QueuedMessage from "../stores/objects/QueuedMessage";
|
||||
import { Globals, RouteSettings } from "./Globals";
|
||||
import Logger from "./Logger";
|
||||
|
||||
@ -142,13 +143,22 @@ export default class REST {
|
||||
body: FormData,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
queryParams: Record<string, any> = {},
|
||||
progressCb?: (ev: ProgressEvent) => void,
|
||||
msg?: QueuedMessage,
|
||||
): Promise<U> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = REST.makeAPIUrl(path, queryParams);
|
||||
this.logger.debug(`POST ${url}; payload:`, body);
|
||||
const xhr = new XMLHttpRequest();
|
||||
if (progressCb) xhr.upload.addEventListener("progress", progressCb);
|
||||
if (msg) {
|
||||
// add abort callback
|
||||
msg.setAbortCallback(() => {
|
||||
this.logger.debug("[PostFormData]: Message called abort");
|
||||
xhr.abort();
|
||||
reject("aborted");
|
||||
});
|
||||
// add progress listener
|
||||
xhr.upload.addEventListener("progress", (e: ProgressEvent) => msg.updateProgress(e));
|
||||
}
|
||||
xhr.addEventListener("loadend", () => {
|
||||
// if success, resolve text or json
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
|
Loading…
Reference in New Issue
Block a user