mirror of
https://github.com/stoatchat/for-legacy-web.git
synced 2026-03-08 01:45:28 +00:00
Mobile reactions and WS reconnection
* [feat] Add reaction menu item for mobile clients. * [fix] Reconnection to the websocket with exponential backoff. * [chore] Dev flake. * [hack] Push to my personal gcr.
This commit is contained in:
@@ -28,6 +28,7 @@ type Transition =
|
||||
| "SUCCESS"
|
||||
| "DISCONNECT"
|
||||
| "RETRY"
|
||||
| "RETRY_FAILED"
|
||||
| "LOGOUT"
|
||||
| "ONLINE"
|
||||
| "OFFLINE";
|
||||
@@ -40,6 +41,7 @@ export default class Session {
|
||||
state: State = window.navigator.onLine ? "Ready" : "Offline";
|
||||
user_id: string | null = null;
|
||||
client: Client | null = null;
|
||||
retryAttempts: number = 0;
|
||||
|
||||
/**
|
||||
* Create a new Session
|
||||
@@ -89,9 +91,11 @@ export default class Session {
|
||||
* Called when the client signals it has disconnected
|
||||
*/
|
||||
private onDropped() {
|
||||
this.emit({
|
||||
action: "DISCONNECT",
|
||||
});
|
||||
if (this.state === "Connecting") {
|
||||
this.emit({ action: "RETRY_FAILED" });
|
||||
} else {
|
||||
this.emit({ action: "DISCONNECT" });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,6 +215,7 @@ export default class Session {
|
||||
// Ready successfully received
|
||||
case "SUCCESS": {
|
||||
this.assert("Connecting");
|
||||
this.retryAttempts = 0;
|
||||
this.state = "Online";
|
||||
break;
|
||||
}
|
||||
@@ -239,6 +244,18 @@ export default class Session {
|
||||
this.state = "Connecting";
|
||||
break;
|
||||
}
|
||||
// Reconnect attempt failed, schedule another with backoff
|
||||
case "RETRY_FAILED": {
|
||||
this.assert("Connecting");
|
||||
this.retryAttempts++;
|
||||
const delay = Math.min(500 * Math.pow(2, this.retryAttempts), 16000);
|
||||
setTimeout(() => {
|
||||
if (this.state === "Connecting") {
|
||||
this.client!.websocket.connect();
|
||||
}
|
||||
}, delay);
|
||||
break;
|
||||
}
|
||||
// User instructed logout
|
||||
case "LOGOUT": {
|
||||
this.assert("Connecting", "Online", "Disconnected");
|
||||
|
||||
@@ -32,6 +32,7 @@ import CreateRole from "./components/CreateRole";
|
||||
import CreateServer from "./components/CreateServer";
|
||||
import CustomStatus from "./components/CustomStatus";
|
||||
import DeleteMessage from "./components/DeleteMessage";
|
||||
import ReactMessage from "./components/ReactMessage";
|
||||
import Error from "./components/Error";
|
||||
import ImageViewer from "./components/ImageViewer";
|
||||
import KickMember from "./components/KickMember";
|
||||
@@ -275,6 +276,7 @@ export const modalController = new ModalControllerExtended({
|
||||
create_bot: CreateBot,
|
||||
custom_status: CustomStatus,
|
||||
delete_message: DeleteMessage,
|
||||
react_message: ReactMessage,
|
||||
error: Error,
|
||||
image_viewer: ImageViewer,
|
||||
kick_member: KickMember,
|
||||
|
||||
46
src/controllers/modals/components/ReactMessage.tsx
Normal file
46
src/controllers/modals/components/ReactMessage.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
import { ModalProps } from "../types"
|
||||
|
||||
import { Message } from "revolt.js";
|
||||
import { emojiDictionary } from "../../../assets/emojis"
|
||||
import { HackAlertThisFileWillBeReplaced } from "../../../components/common/messaging/MessageBox"
|
||||
|
||||
const PickerContainer = styled.div`
|
||||
max-height: 420px;
|
||||
max-width: 370px;
|
||||
overflow: hidden;
|
||||
|
||||
> div {
|
||||
position: unset;
|
||||
}
|
||||
`
|
||||
|
||||
export default function ReactMessage({
|
||||
target: message,
|
||||
onClose,
|
||||
...props
|
||||
}: ModalProps<"react_message">) {
|
||||
return (
|
||||
<Modal
|
||||
{...props}
|
||||
padding={false}
|
||||
maxWidth="370px"
|
||||
>
|
||||
<PickerContainer>
|
||||
<HackAlertThisFileWillBeReplaced
|
||||
onSelect={(emoji) =>{
|
||||
message.react(
|
||||
emojiDictionary[
|
||||
emoji as keyof typeof emojiDictionary
|
||||
] ?? emoji,
|
||||
);
|
||||
onClose();
|
||||
}}
|
||||
onClose={onClose}
|
||||
/>
|
||||
</PickerContainer>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
@@ -153,6 +153,10 @@ export type Modal = {
|
||||
type: "delete_message";
|
||||
target: Message;
|
||||
}
|
||||
| {
|
||||
type: "react_message",
|
||||
target: Message;
|
||||
}
|
||||
| {
|
||||
type: "kick_member";
|
||||
member: Member;
|
||||
|
||||
@@ -65,6 +65,7 @@ type Action =
|
||||
| { action: "quote_message"; content: string }
|
||||
| { action: "edit_message"; id: string }
|
||||
| { action: "delete_message"; target: Message }
|
||||
| { action: "react_message"; target: Message }
|
||||
| { action: "open_file"; attachment: API.File }
|
||||
| { action: "save_file"; attachment: API.File }
|
||||
| { action: "copy_file_link"; attachment: API.File }
|
||||
@@ -402,6 +403,13 @@ export default function ContextMenus() {
|
||||
});
|
||||
break;
|
||||
|
||||
case "react_message":
|
||||
modalController.push({
|
||||
type: "react_message",
|
||||
target: data.target,
|
||||
});
|
||||
break;
|
||||
|
||||
case "leave_group":
|
||||
case "close_dm":
|
||||
case "delete_channel":
|
||||
@@ -508,6 +516,8 @@ export default function ContextMenus() {
|
||||
"Open in Admin Panel"
|
||||
) : locale === "admin_system" ? (
|
||||
"Open User in Admin Panel"
|
||||
) : locale === "react_message" ? (
|
||||
"React"
|
||||
) : (
|
||||
<Text
|
||||
id={`app.context_menu.${
|
||||
@@ -833,6 +843,16 @@ export default function ContextMenus() {
|
||||
});
|
||||
}
|
||||
|
||||
if (message.channel?.havePermission("React")) {
|
||||
generateAction(
|
||||
{
|
||||
action: "react_message",
|
||||
target: message,
|
||||
},
|
||||
"react_message",
|
||||
);
|
||||
}
|
||||
|
||||
if (message.author_id !== userId) {
|
||||
generateAction(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user