From c1771da8cc2b08485bf20c0ebec26f41aaa1a17b Mon Sep 17 00:00:00 2001 From: TeamAbron Date: Sat, 18 Jan 2025 15:02:27 +0330 Subject: [PATCH 01/14] wrong file removed --- .env' | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .env' diff --git a/.env' b/.env' deleted file mode 100644 index 16d366c6..00000000 --- a/.env' +++ /dev/null @@ -1,2 +0,0 @@ -VITE_API_URL=https://test.peptide.chat/api -# VITE_API_URL=http://local.revolt.chat:8000 From e3f5a01f2e815d45c15f6830c417e46eaa73468b Mon Sep 17 00:00:00 2001 From: TeamAbron Date: Sat, 18 Jan 2025 15:06:06 +0330 Subject: [PATCH 02/14] Add pin message --- .../common/messaging/MessageBox.tsx | 150 ++++--- .../common/messaging/PinMessageBox.tsx | 162 +++++++ .../common/messaging/bars/PinnedMessage.tsx | 423 ++++++++++++++++++ src/lib/ContextMenus.tsx | 124 +++-- src/lib/eventEmitter.ts | 2 + src/lib/renderer/simple/SimpleRenderer.ts | 1 + src/pages/channels/Channel.tsx | 6 +- src/pages/channels/messaging/MessageArea.tsx | 39 +- .../channels/messaging/MessageRenderer.tsx | 23 +- yarn.lock | 129 ++++-- 10 files changed, 896 insertions(+), 163 deletions(-) create mode 100644 src/components/common/messaging/PinMessageBox.tsx create mode 100644 src/components/common/messaging/bars/PinnedMessage.tsx diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx index 70ee0633..c38ed11f 100644 --- a/src/components/common/messaging/MessageBox.tsx +++ b/src/components/common/messaging/MessageBox.tsx @@ -55,11 +55,11 @@ export type UploadState = | { type: "none" } | { type: "attached"; files: File[] } | { - type: "uploading"; - files: File[]; - percent: number; - cancel: CancelTokenSource; - } + type: "uploading"; + files: File[]; + percent: number; + cancel: CancelTokenSource; + } | { type: "sending"; files: File[] } | { type: "failed"; files: File[]; error: string }; @@ -257,25 +257,27 @@ export default observer(({ channel }: Props) => { ); } - console.log(channel) - if (!channel.havePermission("SendMessage") && channel.recipient?.relationship == "Blocked" || channel.recipient?.relationship == "BlockedOther"){ - return ( - - - - - - - -
- -
-
- - ); - } + console.log(channel) //|| channel.channel_type != "DirectMessage" + if (channel.channel_type != "SavedMessages") + if (!channel.havePermission("SendMessage") && channel.channel_type == "TextChannel" || channel.recipient?.relationship == "Blocked" || channel.recipient?.relationship == "BlockedOther") { + + return ( + + + + + + + +
+ +
+
+ + ); + } // Push message content to draft. const setMessage = useCallback( (content?: string) => { @@ -297,9 +299,9 @@ export default observer(({ channel }: Props) => { const text = action === "quote" ? `${content - .split("\n") - .map((x) => `> ${x}`) - .join("\n")}\n\n` + .split("\n") + .map((x) => `> ${x}`) + .join("\n")}\n\n` : `${content} `; if (!state.draft.has(channel._id)) { @@ -353,8 +355,8 @@ export default observer(({ channel }: Props) => { toReplace == "" ? msg.content.toString() + newText : msg.content - .toString() - .replace(new RegExp(toReplace, flags), newText); + .toString() + .replace(new RegExp(toReplace, flags), newText); if (newContent != msg.content) { if (newContent.length == 0) { @@ -432,10 +434,10 @@ export default observer(({ channel }: Props) => { files, percent: Math.round( (i * 100 + (100 * e.loaded) / e.total) / - Math.min( - files.length, - CAN_UPLOAD_AT_ONCE, - ), + Math.min( + files.length, + CAN_UPLOAD_AT_ONCE, + ), ), cancel, }), @@ -628,42 +630,42 @@ export default observer(({ channel }: Props) => { {/* {channel.havePermission("UploadFiles") ? ( */} - - - setUploadState({ type: "none" }) - } - onChange={(files) => - setUploadState({ type: "attached", files }) - } - cancel={() => - uploadState.type === "uploading" && - uploadState.cancel.cancel("cancel") - } - append={(files) => { - if (files.length === 0) return; + + + setUploadState({ type: "none" }) + } + onChange={(files) => + setUploadState({ type: "attached", files }) + } + cancel={() => + uploadState.type === "uploading" && + uploadState.cancel.cancel("cancel") + } + append={(files) => { + if (files.length === 0) return; - if (uploadState.type === "none") { - setUploadState({ type: "attached", files }); - } else if (uploadState.type === "attached") { - setUploadState({ - type: "attached", - files: [...uploadState.files, ...files], - }); - } - }} - /> - + if (uploadState.type === "none") { + setUploadState({ type: "attached", files }); + } else if (uploadState.type === "attached") { + setUploadState({ + type: "attached", + files: [...uploadState.files, ...files], + }); + } + }} + /> + {/* ) : ( )} */} @@ -726,13 +728,13 @@ export default observer(({ channel }: Props) => { placeholder={ channel.channel_type === "DirectMessage" ? translate("app.main.channel.message_who", { - person: channel.recipient?.username, - }) + person: channel.recipient?.username, + }) : channel.channel_type === "SavedMessages" - ? translate("app.main.channel.message_saved") - : translate("app.main.channel.message_where", { - channel_name: channel.name ?? undefined, - }) + ? translate("app.main.channel.message_saved") + : translate("app.main.channel.message_where", { + channel_name: channel.name ?? undefined, + }) } disabled={ uploadState.type === "uploading" || diff --git a/src/components/common/messaging/PinMessageBox.tsx b/src/components/common/messaging/PinMessageBox.tsx new file mode 100644 index 00000000..4fa9ba28 --- /dev/null +++ b/src/components/common/messaging/PinMessageBox.tsx @@ -0,0 +1,162 @@ +import { + InfoCircle, + UserPlus, + UserMinus, + ArrowToRight, + ArrowToLeft, + UserX, + ShieldX, + EditAlt, + Edit, + MessageSquareEdit, + Key, +} from "@styled-icons/boxicons-solid"; +import { observer } from "mobx-react-lite"; +import { Message, Channel, API } from "revolt.js"; +import styled from "styled-components/macro"; +import { decodeTime } from "ulid"; + +import { useTriggerEvents } from "preact-context-menu"; +import { Text } from "preact-i18n"; + +import { Row } from "@revoltchat/ui"; + +import { TextReact } from "../../../lib/i18n"; + +import { useApplicationState } from "../../../mobx/State"; + +import { dayjs } from "../../../context/Locale"; + +import Markdown from "../../markdown/Markdown"; +import Tooltip from "../Tooltip"; +import UserShort from "../user/UserShort"; +import MessageBase, { MessageDetail, MessageInfo } from "./MessageBase"; +import { Pin } from "@styled-icons/boxicons-regular"; +import { useHistory } from "react-router-dom"; + +const SystemContent = styled.div` + gap: 4px; + display: flex; + padding: 2px 0; + flex-wrap: wrap; + align-items: center; + flex-direction: row; + font-size: 14px; + color: var(--secondary-foreground); + + span { + font-weight: 600; + color: var(--foreground); + } + + svg { + margin-inline-end: 4px; + } + + svg, + span { + cursor: pointer; + } + + span:hover { + text-decoration: underline; + } +`; + +interface Props { + attachContext?: boolean; + message: Message; + highlight?: boolean; + hideInfo?: boolean; + channel: Channel +} + +const iconDictionary = { + user_added: UserPlus, + user_remove: UserMinus, + user_joined: ArrowToRight, + user_left: ArrowToLeft, + user_kicked: UserX, + user_banned: ShieldX, + channel_renamed: EditAlt, + channel_description_changed: Edit, + channel_icon_changed: MessageSquareEdit, + channel_ownership_changed: Key, + text: InfoCircle, +}; + +export const PinMessageBox = observer( + ({ attachContext, message, channel, highlight, hideInfo }: Props) => { + const data: any = message.system + if (!data) return null; + const history = useHistory(); + + + let children = null; + let userName = message.client ? message.client.user?.username : "" + + + if (data.type as string == "message_pinned") { + children = children = ( +
{ + if (channel.channel_type === "TextChannel") { + history.push( + `/server/${channel.server_id}/channel/${channel._id}/${data.id}`, + ); + } else { + history.push(`/channel/${channel._id}/${data.id}`); + } + }} + > + +
+ ); + } + if (data.type as string == "message_unpinned") { + children = children = ( +
{ + if (channel.channel_type === "TextChannel") { + history.push( + `/server/${channel.server_id}/channel/${channel._id}/${data.id}`, + ); + } else { + history.push(`/channel/${channel._id}/${data.id}`); + } + }} + > + +
+ ); + } + + + + return ( + + + + {!hideInfo && ( + + + {/* */} + + )} + + + {children} + + ); + }, +); diff --git a/src/components/common/messaging/bars/PinnedMessage.tsx b/src/components/common/messaging/bars/PinnedMessage.tsx new file mode 100644 index 00000000..793ac0ae --- /dev/null +++ b/src/components/common/messaging/bars/PinnedMessage.tsx @@ -0,0 +1,423 @@ +import { LeftArrow, LeftArrowAlt, Pin, UpArrowAlt } from "@styled-icons/boxicons-regular"; +import { observer } from "mobx-react-lite"; +import { useHistory } from "react-router-dom"; +import { Channel } from "revolt.js"; +import { decodeTime } from "ulid"; + +import { Text } from "preact-i18n"; +import { useEffect, useState } from "preact/hooks"; + +import { internalSubscribe } from "../../../../lib/eventEmitter"; +import { getRenderer } from "../../../../lib/renderer/Singleton"; + +import { dayjs } from "../../../../context/Locale"; +import styled, { css } from "styled-components/macro"; + +import classNames from "classnames"; +import { isTouchscreenDevice } from "../../../../lib/isTouchscreenDevice"; +import { useClient } from "../../../../controllers/client/ClientController"; +import { Message } from "revolt.js/esm"; +export const PinBar = styled.div<{ position: "top" | "bottom"; accent?: boolean }>` + z-index: 2; + position: relative; + + @keyframes bottomBounce { + 0% { + transform: translateY(33px); + } + 100% { + transform: translateY(0px); + } + } + + @keyframes topBounce { + 0% { + transform: translateY(-33px); + } + 100% { + transform: translateY(0px); + } + } + + ${(props) => + props.position === "top" && + css` + top: 0; + + + animation: topBounce 1s cubic-bezier(0.2, 0.9, 0.5, 1.16) + forwards; + `} + + ${(props) => + props.position === "bottom" && + css` + top: -28px; + animation: bottomBounce 340ms cubic-bezier(0.2, 0.9, 0.5, 1.16) + forwards; + + ${() => + isTouchscreenDevice && + css` + top: -90px; + `} + `} + + > div { + min-height: 120px; + max-height: 200px; + + height: auto; + width: 40%; + right : 0px !important; + position: absolute; + display: block; + align-items: center; + cursor: pointer; + font-size: 12px; + font-weight: 600; + padding: 0 8px; + user-select: none; + justify-content: space-between; + transition: color ease-in-out 0.08s; + + white-space: nowrap; + overflow: scroll; + text-overflow: ellipsis; + + ${(props) => + props.accent + ? css` + color: var(--accent-contrast); + background-color: var(--hover)!important; + backdrop-filter: blur(20px); + ` + : css` + color: var(--secondary-foreground); + background-color: rgba( + var(--secondary-background-rgb), + max(var(--min-opacity), 0.9) + ); + backdrop-filter: blur(20px); + `} + + ${(props) => + props.position === "top" + ? css` + top: 48px; + border-radius: 0 0 var(--border-radius) + var(--border-radius); + ` + : css` + border-radius: var(--border-radius) var(--border-radius) 0 + 0; + `} + + ${() => + isTouchscreenDevice && + css` + top: 56px; + `} + + > div { + display: flex; + align-items: center; + gap: 6px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + &:hover { + color: var(--primary-text); + } + + &:active { + transform: translateY(1px); + } + + ${() => + isTouchscreenDevice && + css` + height: 34px; + padding: 0 12px; + `} + } + + @media only screen and (max-width: 800px) { + .right > span { + display: none; + } + } +`; + + + + + +export const PinIcon = styled.div<{ position: "top" | "bottom", accent?: boolean }>` + z-index: 2; + position: relative; + + @keyframes bottomBounce { + 0% { + transform: translateY(33px); + } + 100% { + transform: translateY(0px); + } + } + + @keyframes topBounce { + 0% { + transform: translateY(-33px); + } + 100% { + transform: translateY(0px); + } + } + ${(props) => + props.accent + ? css` + color: var(--accent-contrast); + background-color: var(--hover)!important; + backdrop-filter: blur(20px); + ` + : css` + color: var(--secondary-foreground); + background-color: rgba( + var(--secondary-background-rgb), + max(var(--min-opacity), 0.9) + ); + backdrop-filter: blur(20px); + `} + + ${(props) => + props.position === "top" && + css` + top: 5; + animation: topBounce 1s cubic-bezier(0.2, 0.9, 0.5, 1.16) + forwards; + `} + + + > div { + height: auto; + width: auto; + right : 5px !important; + position: absolute; + display: flex; + align-items: center; + cursor: pointer; + font-size: 12px; + font-weight: 600; + padding: 8px 8px; + user-select: none; + justify-content: space-between; + transition: color ease-in-out 0.08s; + + white-space: nowrap; + + ${(props) => + props.accent + ? css` + color: var(--accent-contrast); + background-color: var(--hover)!important; + backdrop-filter: blur(20px); + ` + : css` + color: var(--secondary-foreground); + background-color: rgba( + var(--secondary-background-rgb), + max(var(--min-opacity), 0.9) + ); + backdrop-filter: blur(20px); + `} + + ${(props) => + props.position === "top" + ? css` + top: 52px; + border-radius: 0 0 var(--border-radius) + var(--border-radius); + ` + : css` + border-radius: var(--border-radius) var(--border-radius) 0 + 0; + `} + + ${() => + isTouchscreenDevice && + css` + top: 56px; + `} + + + } + + @media only screen and (max-width: 800px) { + .right > span { + display: none; + } + } +`; + + + + +export default observer( + ({ channel }: { channel: Channel; }) => { + const [hidden, setHidden] = useState(true); + const unhide = () => setHidden(false); + + // useEffect(() => setHidden(false), [last_id]); + // useEffect(() => internalSubscribe("NewMessages", "hide", hide), []); + // useEffect(() => { + // const onKeyDown = (e: KeyboardEvent) => + // e.key === "Escape" && hide(); + + // document.addEventListener("keydown", onKeyDown); + // return () => document.removeEventListener("keydown", onKeyDown); + // }, []); + + // const extendedMessage = new MessageExtendedClass(client); + + + // useEffect(() => { + // if (last_id) { + // try { + // setTimeAgo(dayjs(decodeTime(last_id)).fromNow()); + // } catch (err) { } + // } + // }, [last_id]); + + const renderer = getRenderer(channel); + const history = useHistory(); + if (renderer.state !== "RENDER") return null; + // if (!last_id) return null; + // if (hidden) return null; + + + // renderer.messages.slice().reverse().map((res, i) => { + // console.log(res, 8989) + // }) + function truncateText(text: string, chars: number) { + if (text.length > chars) { + return text.slice(0, chars) + ".."; + } + return text; + } + + + + let pinFound = false + return ( + <> + +
unhide()} + > + + +
+
+ + + {!hidden && +
+
setHidden(true)} + style={{ + backgroundColor: "var(--block)", + width: "100%", + position: "sticky", + top: "0px", + display: "flex", + + justifyContent: "space-between", + borderRadius: "5px", + padding: "8px 8px" + + }}> + + setHidden(true)} /> + + + +
+ + + +
+ { + + renderer.messages.slice().reverse().map((msg, i) => { + if (msg.is_pinned) { + // console.log(msg, 8989) + let content = msg.content ? truncateText(msg.content, 20) : "" + pinFound = true + return ( + +
{ + // setHidden(true); + if (channel.channel_type === "TextChannel") { + history.push( + `/server/${channel.server_id}/channel/${channel._id}/${msg._id}`, + ); + } else { + history.push(`/channel/${channel._id}/${msg._id}`); + } + }} + + + style={{ display: 'flex', paddingTop: "5px" }}> + <>. {" "} + +
+ ) + } + + }) + + + + } + + {!renderer.atTop &&
{ + // setHidden(true); + renderer.loadTop() + }} + + + style={{ display: 'flex', paddingTop: "5px", justifyContent: "center" }}> + + +
} + +
+ + + + +
+
} + + ); + }, +); diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index b51fd8cc..e3344df5 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -58,6 +58,7 @@ type Action = | { action: "mark_as_read"; channel: Channel } | { action: "mark_server_as_read"; server: Server } | { action: "mark_unread"; message: Message } + | { action: "pin_message"; channel: any; message: any } | { action: "retry_message"; message: QueuedMessage } | { action: "cancel_message"; message: QueuedMessage } | { action: "mention"; user: string } @@ -87,32 +88,32 @@ type Action = | { action: "create_channel"; target: Server } | { action: "create_category"; target: Server } | { - action: "create_invite"; - target: Channel; - } + action: "create_invite"; + target: Channel; + } | { action: "leave_group"; target: Channel } | { - action: "delete_channel"; - target: Channel; - } + action: "delete_channel"; + target: Channel; + } | { action: "close_dm"; target: Channel } | { action: "leave_server"; target: Server } | { action: "delete_server"; target: Server } | { action: "edit_identity"; target: Member } | { - action: "open_notification_options"; - channel?: Channel; - server?: Server; - } + action: "open_notification_options"; + channel?: Channel; + server?: Server; + } | { action: "open_settings" } | { action: "open_channel_settings"; id: string } | { action: "open_server_settings"; id: string } | { action: "open_server_channel_settings"; server: string; id: string } | { - action: "set_notification_state"; - key: string; - state?: NotificationState; - } + action: "set_notification_state"; + key: string; + state?: NotificationState; + } | { action: "report"; target: User | Server | Message; messageId?: string }; // ! FIXME: I dare someone to re-write this @@ -202,8 +203,50 @@ export default function ContextMenus() { internalEmit("NewMessages", "mark", unread_id); data.message.channel?.ack(unread_id, true); } + case "pin_message": + { + + + const messages = getRenderer( + data.message.channel!, + ).messages; + const index = messages.findIndex( + (x) => x._id === data.message._id, + ); + let message + + if (index > 0) { + message = messages[index]; + } + + internalEmit("MessageBox", "pin", message); + + // data.message.channel?.ack(pin_id, true); + } break; + + case "unpin_message": + { + + + const messages = getRenderer( + data.message.channel!, + ).messages; + const index = messages.findIndex( + (x) => x._id === data.message._id, + ); + let message + + if (index > 0) { + message = messages[index]; + } + + internalEmit("MessageBox", "unpin", message); + + // data.message.channel?.ack(pin_id, true); + } + break; case "retry_message": { const nonce = data.message.id; @@ -513,9 +556,8 @@ export default function ContextMenus() { "Open User in Admin Panel" ) : ( )} @@ -573,7 +615,7 @@ export default function ContextMenus() { const user = uid ? client.users.get(uid) : undefined; const serverChannel = targetChannel && - (targetChannel.channel_type === "TextChannel") + (targetChannel.channel_type === "TextChannel") ? targetChannel : undefined; @@ -585,8 +627,8 @@ export default function ContextMenus() { (server ? server.permission : serverChannel - ? serverChannel.server?.permission - : 0) || 0; + ? serverChannel.server?.permission + : 0) || 0; const userPermissions = (user ? user.permission : 0) || 0; if (unread) { @@ -810,6 +852,24 @@ export default function ContextMenus() { action: "mark_unread", message, }); + if (sendPermission) { + + + if (message.is_pinned) { + generateAction({ + action: "unpin_message", + channel, + message + }); + } else { + generateAction({ + action: "pin_message", + channel, + message + }); + } + + } if ( typeof message.content === "string" && @@ -880,8 +940,8 @@ export default function ContextMenus() { type === "Image" ? "open_image" : type === "Video" - ? "open_video" - : "open_file", + ? "open_video" + : "open_file", ); generateAction( @@ -892,8 +952,8 @@ export default function ContextMenus() { type === "Image" ? "save_image" : type === "Video" - ? "save_video" - : "save_file", + ? "save_video" + : "save_file", ); generateAction( @@ -929,8 +989,8 @@ export default function ContextMenus() { type === "Image" ? "open_image" : type === "Video" - ? "open_video" - : "open_file", + ? "open_video" + : "open_file", ); generateAction( @@ -941,8 +1001,8 @@ export default function ContextMenus() { type === "Image" ? "save_image" : type === "Video" - ? "save_video" - : "save_file", + ? "save_video" + : "save_file", ); generateAction( @@ -1130,8 +1190,8 @@ export default function ContextMenus() { type: cid ? "channel" : message - ? "message" - : "user", + ? "message" + : "user", }, "admin", ); @@ -1158,8 +1218,8 @@ export default function ContextMenus() { cid ? "copy_cid" : message - ? "copy_mid" - : "copy_uid", + ? "copy_mid" + : "copy_uid", ); } } diff --git a/src/lib/eventEmitter.ts b/src/lib/eventEmitter.ts index c54460a9..85cebc7c 100644 --- a/src/lib/eventEmitter.ts +++ b/src/lib/eventEmitter.ts @@ -25,6 +25,8 @@ export function internalEmit(ns: string, event: string, ...args: unknown[]) { // - Intermediate/open_profile // - Intermediate/navigate // - MessageBox/append +// - MessageBox/pin +// - MessageBox/unpin // - TextArea/focus // - ReplyBar/add // - Modal/close diff --git a/src/lib/renderer/simple/SimpleRenderer.ts b/src/lib/renderer/simple/SimpleRenderer.ts index 98db77b6..19222589 100644 --- a/src/lib/renderer/simple/SimpleRenderer.ts +++ b/src/lib/renderer/simple/SimpleRenderer.ts @@ -28,6 +28,7 @@ export const SimpleRenderer: RendererRoutines = { renderer.channel .fetchMessagesWithUsers({}) .then(({ messages }) => { + console.log(messages, 9090); messages.reverse(); runInAction(() => { diff --git a/src/pages/channels/Channel.tsx b/src/pages/channels/Channel.tsx index ae219cb2..32418e39 100644 --- a/src/pages/channels/Channel.tsx +++ b/src/pages/channels/Channel.tsx @@ -26,6 +26,7 @@ import { PageHeader } from "../../components/ui/Header"; import { useClient } from "../../controllers/client/ClientController"; import ChannelHeader from "./ChannelHeader"; import { MessageArea } from "./messaging/MessageArea"; +import PinnedMessage from "../../components/common/messaging/bars/PinnedMessage"; const ChannelMain = styled.div.attrs({ "data-component": "channel" })` flex-grow: 1; @@ -99,7 +100,7 @@ export const Channel = observer( const client = useClient(); const state = useApplicationState(); - if (!client.channels.exists(id) && client.servers.get(server_id)) { + if (!client.channels.exists(id) && server_id) { if (server_id) { const server = client.servers.get(server_id); if (server && server.channel_ids.length > 0) { @@ -110,7 +111,7 @@ export const Channel = observer( target_id = last_id; } } - + return ( { + diff --git a/src/pages/channels/messaging/MessageArea.tsx b/src/pages/channels/messaging/MessageArea.tsx index d0ae8a5f..375d1a39 100644 --- a/src/pages/channels/messaging/MessageArea.tsx +++ b/src/pages/channels/messaging/MessageArea.tsx @@ -23,11 +23,12 @@ import { internalEmit, internalSubscribe } from "../../../lib/eventEmitter"; import { getRenderer } from "../../../lib/renderer/Singleton"; import { ScrollState } from "../../../lib/renderer/types"; -import { useSession } from "../../../controllers/client/ClientController"; +import { useClient, useSession } from "../../../controllers/client/ClientController"; import RequiresOnline from "../../../controllers/client/jsx/RequiresOnline"; import { modalController } from "../../../controllers/modals/ModalController"; import ConversationStart from "./ConversationStart"; import MessageRenderer from "./MessageRenderer"; +import { Message } from "revolt.js/esm"; const Area = styled.div.attrs({ "data-scroll-offset": "with-padding" })` height: 100%; @@ -115,8 +116,8 @@ export const MessageArea = observer(({ last_id, channel }: Props) => { 101, ref.current ? ref.current.scrollTop + - (ref.current.scrollHeight - - scrollState.current.previousHeight) + (ref.current.scrollHeight - + scrollState.current.previousHeight) : 101, ), { @@ -148,20 +149,48 @@ export const MessageArea = observer(({ last_id, channel }: Props) => { const atBottom = (offset = 0) => ref.current ? Math.floor(ref.current?.scrollHeight - ref.current?.scrollTop) - - offset <= - ref.current?.clientHeight + offset <= + ref.current?.clientHeight : true; const atTop = (offset = 0) => ref.current ? ref.current.scrollTop <= offset : false; + const client = useClient() + function pin(message: Message) { + client.api.post(`/channels/${message.channel_id}/messages/${message._id}/pin` as any) + message.is_pinned = true + } + function unpin(message: Message) { + client.api.delete(`/channels/${message.channel_id}/messages/${message._id}/pin` as any) + message.is_pinned = false + } // ? Handle global jump to bottom, e.g. when editing last message in chat. useEffect(() => { + return internalSubscribe("MessageArea", "jump_to_bottom", () => setScrollState({ type: "ScrollToBottom" }), ); }, [setScrollState]); + useEffect(() => { + + + return internalSubscribe( + "MessageBox", + "pin", + pin as (...args: unknown[]) => void, + ); + }, []); + useEffect(() => { + + + return internalSubscribe( + "MessageBox", + "unpin", + unpin as (...args: unknown[]) => void, + ); + }, []); // ? Handle events from renderer. useLayoutEffect( () => setScrollState(renderer.scrollState), diff --git a/src/pages/channels/messaging/MessageRenderer.tsx b/src/pages/channels/messaging/MessageRenderer.tsx index 950c56d5..c9ad66a3 100644 --- a/src/pages/channels/messaging/MessageRenderer.tsx +++ b/src/pages/channels/messaging/MessageRenderer.tsx @@ -23,6 +23,7 @@ import { useClient } from "../../../controllers/client/ClientController"; import RequiresOnline from "../../../controllers/client/jsx/RequiresOnline"; import ConversationStart from "./ConversationStart"; import MessageEditor from "./MessageEditor"; +import { PinMessageBox } from "../../../components/common/messaging/PinMessageBox"; interface Props { last_id?: string; @@ -150,8 +151,9 @@ export default observer(({ last_id, renderer, highlight }: Props) => { ); blocked = 0; } + let lastPinned = null - for (const message of renderer.messages) { + for (const [i, message] of renderer.messages.entries()) { if (previous) { compare( message._id, @@ -162,8 +164,21 @@ export default observer(({ last_id, renderer, highlight }: Props) => { previous.masquerade, ); } + // console.log(renderer.messages[i].content, 7979) - if (message.author_id === "00000000000000000000000000") { + + if (message.system?.type as any == "message_pinned" || message.system?.type as any == "message_unpinned") { + render.push( + + , + ); + } else if (message.author_id === "00000000000000000000000000") { render.push( { attachContext highlight={highlight === message._id} />, - ); + ) } else if (message.author?.relationship === "Blocked") { blocked++; } else { @@ -204,6 +219,7 @@ export default observer(({ last_id, renderer, highlight }: Props) => { const nonces = renderer.messages.map((x) => x.nonce); if (renderer.atBottom) { for (const msg of queue.get(renderer.channel._id)) { + if (nonces.includes(msg.id)) continue; if (previous) { @@ -222,6 +238,7 @@ export default observer(({ last_id, renderer, highlight }: Props) => { } as MessageI; } + render.push( = 0.14.0" + react-dom: ">= 0.14.0" + checksum: 42d9b3182b9d2495bf0d7914c9f370da51d8bdb853a3eba2acaf433894ae760386a075ba103185be825b33d42f50d85ef462087f261656d433f4c74dab23861f + languageName: node + linkType: hard + "react-fast-compare@npm:^3.1.1": version: 3.2.0 resolution: "react-fast-compare@npm:3.2.0" @@ -9068,12 +9092,12 @@ __metadata: linkType: hard "typescript@npm:^4.6.2": - version: 4.6.4 - resolution: "typescript@npm:4.6.4" + version: 4.9.5 + resolution: "typescript@npm:4.9.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: e7bfcc39cd4571a63a54e5ea21f16b8445268b9900bf55aee0e02ad981be576acc140eba24f1af5e3c1457767c96cea6d12861768fb386cf3ffb34013718631a + checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db languageName: node linkType: hard @@ -9088,12 +9112,12 @@ __metadata: linkType: hard "typescript@patch:typescript@^4.6.2#~builtin": - version: 4.6.4 - resolution: "typescript@patch:typescript@npm%3A4.6.4#~builtin::version=4.6.4&hash=bda367" + version: 4.9.5 + resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=bda367" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 1cb434fbc637d347be90e3a0c6cd05e33c38f941713c8786d3031faf1842c2c148ba91d2fac01e7276b0ae3249b8633f1660e32686cc7a8c6a8fd5361dc52c66 + checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 languageName: node linkType: hard @@ -9104,6 +9128,15 @@ __metadata: languageName: node linkType: hard +"ua-parser-js@npm:^1.0.33": + version: 1.0.40 + resolution: "ua-parser-js@npm:1.0.40" + bin: + ua-parser-js: script/cli.js + checksum: ae555a33dc9395dd877e295d6adbf5634e047aad7c3358328830218f3ca3a6233e35848cd355465a7612f269860e8029984389282940c7a27c9af4dfcdbba8c3 + languageName: node + linkType: hard + "ulid@npm:^2.3.0": version: 2.3.0 resolution: "ulid@npm:2.3.0" @@ -9125,10 +9158,12 @@ __metadata: languageName: node linkType: hard -"undici@npm:^4.14.1": - version: 4.16.0 - resolution: "undici@npm:4.16.0" - checksum: 5e88c2b3381085e25ed1d1a308610ac7ee985f478ac705af7a8e03213536e10f73ef8dd8d85e6ed38948d1883fa0ae935e04357c317b0f5d3d3c0211d0c8c393 +"undici@npm:^5.4.0": + version: 5.28.4 + resolution: "undici@npm:5.28.4" + dependencies: + "@fastify/busboy": ^2.0.0 + checksum: a8193132d84540e4dc1895ecc8dbaa176e8a49d26084d6fbe48a292e28397cd19ec5d13bc13e604484e76f94f6e334b2bdc740d5f06a6e50c44072818d0c19f9 languageName: node linkType: hard @@ -9794,17 +9829,17 @@ __metadata: linkType: hard "ws@npm:^8.2.2": - version: 8.2.2 - resolution: "ws@npm:8.2.2" + version: 8.18.0 + resolution: "ws@npm:8.18.0" peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 + utf-8-validate: ">=5.0.2" peerDependenciesMeta: bufferutil: optional: true utf-8-validate: optional: true - checksum: 25e764c631141bdca45badc86e69437b8791e57e461f9a16c0f7cd779baf70c3fbba07ecdd9e0d34fea1155ddcf62ef165cd7f81b68ed545bc7d455c15a85fb0 + checksum: 91d4d35bc99ff6df483bdf029b9ea4bfd7af1f16fc91231a96777a63d263e1eabf486e13a2353970efc534f9faa43bdbf9ee76525af22f4752cbc5ebda333975 languageName: node linkType: hard @@ -9822,10 +9857,10 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^21.0.0": - version: 21.0.1 - resolution: "yargs-parser@npm:21.0.1" - checksum: c3ea2ed12cad0377ce3096b3f138df8267edf7b1aa7d710cd502fe16af417bafe4443dd71b28158c22fcd1be5dfd0e86319597e47badf42ff83815485887323a +"yargs-parser@npm:^21.0.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: ed2d96a616a9e3e1cc7d204c62ecc61f7aaab633dcbfab2c6df50f7f87b393993fe6640d017759fe112d0cb1e0119f2b4150a87305cc873fd90831c6a58ccf1c languageName: node linkType: hard From b05542ccbcfaf8db6609a113fe6a416df14b532d Mon Sep 17 00:00:00 2001 From: TeamAbron Date: Sun, 19 Jan 2025 10:05:51 +0330 Subject: [PATCH 03/14] revert yarn.lock file --- yarn.lock | 129 ++++++++++++++++++++---------------------------------- 1 file changed, 47 insertions(+), 82 deletions(-) diff --git a/yarn.lock b/yarn.lock index 18f74230..1e454485 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1841,13 +1841,6 @@ __metadata: languageName: node linkType: hard -"@fastify/busboy@npm:^2.0.0": - version: 2.1.1 - resolution: "@fastify/busboy@npm:2.1.1" - checksum: 42c32ef75e906c9a4809c1e1930a5ca6d4ddc8d138e1a8c8ba5ea07f997db32210617d23b2e4a85fe376316a41a1a0439fc6ff2dedf5126d96f45a9d80754fb2 - languageName: node - linkType: hard - "@floating-ui/core@npm:^1.0.0": version: 1.0.0 resolution: "@floating-ui/core@npm:1.0.0" @@ -5035,13 +5028,23 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.8": - version: 1.15.9 - resolution: "follow-redirects@npm:1.15.9" +"follow-redirects@npm:^1.14.0": + version: 1.14.4 + resolution: "follow-redirects@npm:1.14.4" peerDependenciesMeta: debug: optional: true - checksum: 859e2bacc7a54506f2bf9aacb10d165df78c8c1b0ceb8023f966621b233717dab56e8d08baadc3ad3b9db58af290413d585c999694b7c146aaf2616340c3d2a6 + checksum: d4ce74cf5c6f363168b97e706b914eb9ffb6bf4d4c6d8f8330b93088d9b90e566611ddbcf0e42c8ed5fd17598dfeda1d19230d3e9d6d6c6b4d1c10ec3a0b99be + languageName: node + linkType: hard + +"follow-redirects@npm:^1.14.8": + version: 1.14.9 + resolution: "follow-redirects@npm:1.14.9" + peerDependenciesMeta: + debug: + optional: true + checksum: f5982e0eb481818642492d3ca35a86989c98af1128b8e1a62911a3410621bc15d2b079e8170b35b19d3bdee770b73ed431a257ed86195af773771145baa57845 languageName: node linkType: hard @@ -7053,7 +7056,7 @@ __metadata: languageName: node linkType: hard -"mobx-react-lite@npm:3.4.0": +"mobx-react-lite@npm:3.4.0, mobx-react-lite@npm:^3.4.0": version: 3.4.0 resolution: "mobx-react-lite@npm:3.4.0" peerDependencies: @@ -7068,25 +7071,10 @@ __metadata: languageName: node linkType: hard -"mobx-react-lite@npm:^3.4.0": - version: 3.4.3 - resolution: "mobx-react-lite@npm:3.4.3" - peerDependencies: - mobx: ^6.1.0 - react: ^16.8.0 || ^17 || ^18 - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - checksum: 60a2580eb9a0b9988fc76959d7299f018733dc33cacaa73c45500953006d4d45e738d9ae39ccfc767ac19a75656dbc028d833282c848fbc67d8d18a2bcb5c262 - languageName: node - linkType: hard - "mobx@npm:^6.3.2": - version: 6.13.5 - resolution: "mobx@npm:6.13.5" - checksum: 2a253e505900169326873b573660dab58ce8284a435c75d77775a665af9eed623c1976a5eab3cfb53561cac4713f70194f49a2b8e4111419a2e4291f51e5485a + version: 6.3.2 + resolution: "mobx@npm:6.3.2" + checksum: da853901ddd9bc5347f778b1aebfcbf5215d0cb0909fa17a9580dec2915b034b385e8cea6f2a85bd917078a29fcbb129c28be10e61db06c59bd3c94ace15f4a9 languageName: node linkType: hard @@ -7291,18 +7279,18 @@ __metadata: linkType: hard "openapi-typescript@npm:^5.2.0": - version: 5.4.2 - resolution: "openapi-typescript@npm:5.4.2" + version: 5.2.0 + resolution: "openapi-typescript@npm:5.2.0" dependencies: js-yaml: ^4.1.0 mime: ^3.0.0 - prettier: ^2.6.2 + prettier: ^2.5.1 tiny-glob: ^0.2.9 - undici: ^5.4.0 - yargs-parser: ^21.0.1 + undici: ^4.14.1 + yargs-parser: ^21.0.0 bin: openapi-typescript: bin/cli.js - checksum: 7777dfc99dff8971cdfa9c9d965ee6f464fd58ec81ee1add1450c354d7ca09fa48d5aacef27624a203e627cda375fc039516f9fbb2afdf6911b631329fc814a5 + checksum: 193b0d910d1c067dcbb0f079bf2ae29a3bd392cbae82265760e6e96a70221a3d8d7c287c77af845c2b4bfd4c04251f800c838c63a76564e9f1427b47e62fb598 languageName: node linkType: hard @@ -7520,12 +7508,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^2.6.2": - version: 2.8.8 - resolution: "prettier@npm:2.8.8" +"prettier@npm:^2.5.1": + version: 2.6.2 + resolution: "prettier@npm:2.6.2" bin: prettier: bin-prettier.js - checksum: b49e409431bf129dd89238d64299ba80717b57ff5a6d1c1a8b1a28b590d998a34e083fa13573bc732bb8d2305becb4c9a4407f8486c81fa7d55100eb08263cf8 + checksum: 48d08dde8e9fb1f5bccdd205baa7f192e9fc8bc98f86e1b97d919de804e28c806b0e6cc685e4a88211aa7987fa9668f30baae19580d87ced3ed0f2ec6572106f languageName: node linkType: hard @@ -7649,7 +7637,7 @@ __metadata: languageName: node linkType: hard -"react-device-detect@npm:2.2.2": +"react-device-detect@npm:2.2.2, react-device-detect@npm:^2.2.2": version: 2.2.2 resolution: "react-device-detect@npm:2.2.2" dependencies: @@ -7661,18 +7649,6 @@ __metadata: languageName: node linkType: hard -"react-device-detect@npm:^2.2.2": - version: 2.2.3 - resolution: "react-device-detect@npm:2.2.3" - dependencies: - ua-parser-js: ^1.0.33 - peerDependencies: - react: ">= 0.14.0" - react-dom: ">= 0.14.0" - checksum: 42d9b3182b9d2495bf0d7914c9f370da51d8bdb853a3eba2acaf433894ae760386a075ba103185be825b33d42f50d85ef462087f261656d433f4c74dab23861f - languageName: node - linkType: hard - "react-fast-compare@npm:^3.1.1": version: 3.2.0 resolution: "react-fast-compare@npm:3.2.0" @@ -9092,12 +9068,12 @@ __metadata: linkType: hard "typescript@npm:^4.6.2": - version: 4.9.5 - resolution: "typescript@npm:4.9.5" + version: 4.6.4 + resolution: "typescript@npm:4.6.4" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db + checksum: e7bfcc39cd4571a63a54e5ea21f16b8445268b9900bf55aee0e02ad981be576acc140eba24f1af5e3c1457767c96cea6d12861768fb386cf3ffb34013718631a languageName: node linkType: hard @@ -9112,12 +9088,12 @@ __metadata: linkType: hard "typescript@patch:typescript@^4.6.2#~builtin": - version: 4.9.5 - resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=bda367" + version: 4.6.4 + resolution: "typescript@patch:typescript@npm%3A4.6.4#~builtin::version=4.6.4&hash=bda367" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 + checksum: 1cb434fbc637d347be90e3a0c6cd05e33c38f941713c8786d3031faf1842c2c148ba91d2fac01e7276b0ae3249b8633f1660e32686cc7a8c6a8fd5361dc52c66 languageName: node linkType: hard @@ -9128,15 +9104,6 @@ __metadata: languageName: node linkType: hard -"ua-parser-js@npm:^1.0.33": - version: 1.0.40 - resolution: "ua-parser-js@npm:1.0.40" - bin: - ua-parser-js: script/cli.js - checksum: ae555a33dc9395dd877e295d6adbf5634e047aad7c3358328830218f3ca3a6233e35848cd355465a7612f269860e8029984389282940c7a27c9af4dfcdbba8c3 - languageName: node - linkType: hard - "ulid@npm:^2.3.0": version: 2.3.0 resolution: "ulid@npm:2.3.0" @@ -9158,12 +9125,10 @@ __metadata: languageName: node linkType: hard -"undici@npm:^5.4.0": - version: 5.28.4 - resolution: "undici@npm:5.28.4" - dependencies: - "@fastify/busboy": ^2.0.0 - checksum: a8193132d84540e4dc1895ecc8dbaa176e8a49d26084d6fbe48a292e28397cd19ec5d13bc13e604484e76f94f6e334b2bdc740d5f06a6e50c44072818d0c19f9 +"undici@npm:^4.14.1": + version: 4.16.0 + resolution: "undici@npm:4.16.0" + checksum: 5e88c2b3381085e25ed1d1a308610ac7ee985f478ac705af7a8e03213536e10f73ef8dd8d85e6ed38948d1883fa0ae935e04357c317b0f5d3d3c0211d0c8c393 languageName: node linkType: hard @@ -9829,17 +9794,17 @@ __metadata: linkType: hard "ws@npm:^8.2.2": - version: 8.18.0 - resolution: "ws@npm:8.18.0" + version: 8.2.2 + resolution: "ws@npm:8.2.2" peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" + utf-8-validate: ^5.0.2 peerDependenciesMeta: bufferutil: optional: true utf-8-validate: optional: true - checksum: 91d4d35bc99ff6df483bdf029b9ea4bfd7af1f16fc91231a96777a63d263e1eabf486e13a2353970efc534f9faa43bdbf9ee76525af22f4752cbc5ebda333975 + checksum: 25e764c631141bdca45badc86e69437b8791e57e461f9a16c0f7cd779baf70c3fbba07ecdd9e0d34fea1155ddcf62ef165cd7f81b68ed545bc7d455c15a85fb0 languageName: node linkType: hard @@ -9857,10 +9822,10 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^21.0.1": - version: 21.1.1 - resolution: "yargs-parser@npm:21.1.1" - checksum: ed2d96a616a9e3e1cc7d204c62ecc61f7aaab633dcbfab2c6df50f7f87b393993fe6640d017759fe112d0cb1e0119f2b4150a87305cc873fd90831c6a58ccf1c +"yargs-parser@npm:^21.0.0": + version: 21.0.1 + resolution: "yargs-parser@npm:21.0.1" + checksum: c3ea2ed12cad0377ce3096b3f138df8267edf7b1aa7d710cd502fe16af417bafe4443dd71b28158c22fcd1be5dfd0e86319597e47badf42ff83815485887323a languageName: node linkType: hard From 4185d348516ca36718ba3600e92d6633219dee23 Mon Sep 17 00:00:00 2001 From: TeamAbron Date: Sun, 19 Jan 2025 11:34:52 +0330 Subject: [PATCH 04/14] changed submodule Dir --- .gitmodules | 6 ++++-- external/lang | 2 +- external/revolt.js | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index 6b8e9874..03cd9baa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,11 @@ [submodule "external/lang"] path = external/lang - url = https://github.com/revoltchat/translations + url = https://github.com/archem-team/translations + branch = revite-backports [submodule "external/components"] path = external/components url = https://github.com/revoltchat/components [submodule "external/revolt.js"] path = external/revolt.js - url = https://github.com/revoltchat/revolt.js + url = https://github.com/archem-team/revolt.js + branch = revite-backports diff --git a/external/lang b/external/lang index 3195d642..0b00b45c 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 3195d642cd766cb62d34eb2a57ce3a09e775e91f +Subproject commit 0b00b45c86ff2dd9426c205e5e89acf73db8597f diff --git a/external/revolt.js b/external/revolt.js index cd9e84a3..00770257 160000 --- a/external/revolt.js +++ b/external/revolt.js @@ -1 +1 @@ -Subproject commit cd9e84a337c72709b82bb4eca794ec7474a0ee7e +Subproject commit 007702579cd6e611fce79498461e89951387108d From b0b8caebabea984d4d17077d46a42375f842b8b7 Mon Sep 17 00:00:00 2001 From: TeamAbron Date: Tue, 21 Jan 2025 11:33:26 +0330 Subject: [PATCH 05/14] asd --- src/controllers/modals/components/CreateInvite.tsx | 11 +++++++---- src/pages/channels/Channel.tsx | 5 +++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/controllers/modals/components/CreateInvite.tsx b/src/controllers/modals/components/CreateInvite.tsx index d9901a84..10927a5e 100644 --- a/src/controllers/modals/components/CreateInvite.tsx +++ b/src/controllers/modals/components/CreateInvite.tsx @@ -37,6 +37,7 @@ export default function CreateInvite({ }: ModalProps<"create_invite">) { const [processing, setProcessing] = useState(false); const [code, setCode] = useState("abcdef"); + const [url, setUrl] = useState("abcdef"); // Generate an invite code useEffect(() => { @@ -44,7 +45,10 @@ export default function CreateInvite({ target .createInvite() - .then(({ _id }) => setCode(_id)) + .then((res) => { + setUrl(res.url || "default_url"); + setCode(res._id || "default_code"); + }) .catch((err) => modalController.push({ type: "error", error: takeError(err) }), ) @@ -65,7 +69,7 @@ export default function CreateInvite({ ) : ( - https://{window.location.host}/invite/{code} + {url} ), }, @@ -79,11 +83,10 @@ export default function CreateInvite({ children: , onClick: () => modalController.writeText( - `https://${window.location.host}/invite/${code}` + `${url}` ), }, ]} /> ); } - diff --git a/src/pages/channels/Channel.tsx b/src/pages/channels/Channel.tsx index 93b5a554..32418e39 100644 --- a/src/pages/channels/Channel.tsx +++ b/src/pages/channels/Channel.tsx @@ -99,9 +99,10 @@ export const Channel = observer( ({ id, server_id }: { id: string; server_id: string }) => { const client = useClient(); const state = useApplicationState(); - if (!client.channels.get(id)) { + + if (!client.channels.exists(id) && server_id) { if (server_id) { - const server = client.servers.get(server_id); + const server = client.servers.get(server_id); if (server && server.channel_ids.length > 0) { let target_id = server.channel_ids[0]; const last_id = state.layout.getLastOpened(server_id); From f1467582a91601ca81949d3f3572d675bd67f76d Mon Sep 17 00:00:00 2001 From: TeamAbron Date: Tue, 21 Jan 2025 13:01:21 +0330 Subject: [PATCH 06/14] Bug fixed/first message pin --- external/lang | 2 +- src/lib/ContextMenus.tsx | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/external/lang b/external/lang index 3e086477..8ecb9a34 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 3e086477afc52d10d4306871170c30029699b160 +Subproject commit 8ecb9a34b1b459b5280a6351a4044dfa44b68019 diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index e3344df5..35607da2 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -59,6 +59,7 @@ type Action = | { action: "mark_server_as_read"; server: Server } | { action: "mark_unread"; message: Message } | { action: "pin_message"; channel: any; message: any } + | { action: "unpin_message"; channel: any; message: any } | { action: "retry_message"; message: QueuedMessage } | { action: "cancel_message"; message: QueuedMessage } | { action: "mention"; user: string } @@ -213,11 +214,13 @@ export default function ContextMenus() { const index = messages.findIndex( (x) => x._id === data.message._id, ); + let message - if (index > 0) { + if (index > -1) { message = messages[index]; } + console.log(message,7878) internalEmit("MessageBox", "pin", message); From ae53b5b8af9a9d1f92c88f292cdfed76bf63d288 Mon Sep 17 00:00:00 2001 From: TeamAbron Date: Tue, 21 Jan 2025 15:34:13 +0330 Subject: [PATCH 07/14] feature pin message / ui improvment --- .vscode/settings.json | 5 +- .../common/messaging/bars/PinnedMessage.tsx | 83 ++++++++++++++----- src/lib/ContextMenus.tsx | 2 +- 3 files changed, 68 insertions(+), 22 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 324a9612..50975ba9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,7 @@ { "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true + "editor.formatOnSave": true, + "[typescriptreact]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + } } diff --git a/src/components/common/messaging/bars/PinnedMessage.tsx b/src/components/common/messaging/bars/PinnedMessage.tsx index 793ac0ae..f3beb585 100644 --- a/src/components/common/messaging/bars/PinnedMessage.tsx +++ b/src/components/common/messaging/bars/PinnedMessage.tsx @@ -3,6 +3,7 @@ import { observer } from "mobx-react-lite"; import { useHistory } from "react-router-dom"; import { Channel } from "revolt.js"; import { decodeTime } from "ulid"; +import { isDesktop, isMobile, isTablet } from "react-device-detect"; import { Text } from "preact-i18n"; import { useEffect, useState } from "preact/hooks"; @@ -16,7 +17,9 @@ import styled, { css } from "styled-components/macro"; import classNames from "classnames"; import { isTouchscreenDevice } from "../../../../lib/isTouchscreenDevice"; import { useClient } from "../../../../controllers/client/ClientController"; -import { Message } from "revolt.js/esm"; +import Message from "../Message"; +import { API, Message as MessageI, Nullable } from "revolt.js"; + export const PinBar = styled.div<{ position: "top" | "bottom"; accent?: boolean }>` z-index: 2; position: relative; @@ -42,11 +45,11 @@ export const PinBar = styled.div<{ position: "top" | "bottom"; accent?: boolean ${(props) => props.position === "top" && css` - top: 0; - - + top: 10; animation: topBounce 1s cubic-bezier(0.2, 0.9, 0.5, 1.16) forwards; + + `} ${(props) => @@ -64,12 +67,35 @@ export const PinBar = styled.div<{ position: "top" | "bottom"; accent?: boolean `} > div { - min-height: 120px; - max-height: 200px; + ${() => + isMobile ? + css` + width: 100%; - height: auto; - width: 40%; + + + ` : isDesktop ? + css` + + + + width: 40%; + ` + : + css` + + + + width: 70%; + ` + } + + + right : 0px !important; + height: auto; + max-height: 600px; + min-height: 120px; position: absolute; display: block; align-items: center; @@ -307,6 +333,7 @@ export default observer( } return text; } + const client = useClient() @@ -333,7 +360,7 @@ export default observer( position: "sticky", top: "0px", display: "flex", - + zIndex: 2, justifyContent: "space-between", borderRadius: "5px", padding: "8px 8px" @@ -355,13 +382,11 @@ export default observer( renderer.messages.slice().reverse().map((msg, i) => { if (msg.is_pinned) { - // console.log(msg, 8989) - let content = msg.content ? truncateText(msg.content, 20) : "" + let content = msg.content ? truncateText(msg.content, 220) : "" pinFound = true return (
{ // setHidden(true); if (channel.channel_type === "TextChannel") { @@ -371,19 +396,37 @@ export default observer( } else { history.push(`/channel/${channel._id}/${msg._id}`); } + setHidden(true) }} + style={{ display: 'flex', paddingTop: "5px" }} + > + + - <>. {" "} -
+ //
+ // <>. {" "} + // + //
) } diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index 35607da2..2812fe1a 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -241,7 +241,7 @@ export default function ContextMenus() { ); let message - if (index > 0) { + if (index > -1) { message = messages[index]; } From e993510cdcd1ccb25769597fe2b79bf86cc22cc5 Mon Sep 17 00:00:00 2001 From: TeamAbron Date: Tue, 21 Jan 2025 15:35:05 +0330 Subject: [PATCH 08/14] feature pin message / ui improvment --- .../common/messaging/bars/PinnedMessage.tsx | 37 +------------------ 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/src/components/common/messaging/bars/PinnedMessage.tsx b/src/components/common/messaging/bars/PinnedMessage.tsx index f3beb585..1e0fbf93 100644 --- a/src/components/common/messaging/bars/PinnedMessage.tsx +++ b/src/components/common/messaging/bars/PinnedMessage.tsx @@ -45,11 +45,9 @@ export const PinBar = styled.div<{ position: "top" | "bottom"; accent?: boolean ${(props) => props.position === "top" && css` - top: 10; + top: 0; animation: topBounce 1s cubic-bezier(0.2, 0.9, 0.5, 1.16) forwards; - - `} ${(props) => @@ -71,27 +69,14 @@ export const PinBar = styled.div<{ position: "top" | "bottom"; accent?: boolean isMobile ? css` width: 100%; - - - ` : isDesktop ? css` - - - - width: 40%; - ` + width: 40%;` : css` - - - width: 70%; ` } - - - right : 0px !important; height: auto; max-height: 600px; @@ -400,33 +385,15 @@ export default observer( }} style={{ display: 'flex', paddingTop: "5px" }} > - - //
- // <>. {" "} - // - //
) } From 6fb4d212ee6a604f629de9a53c8c2e47a53c64a0 Mon Sep 17 00:00:00 2001 From: TeamAbronDev Date: Sun, 26 Jan 2025 16:12:26 +0330 Subject: [PATCH 09/14] added pinMessages structure --- src/components/common/messaging/bars/PinnedMessage.tsx | 10 +++++----- src/lib/renderer/Singleton.ts | 1 + src/lib/renderer/simple/SimpleRenderer.ts | 9 +++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/components/common/messaging/bars/PinnedMessage.tsx b/src/components/common/messaging/bars/PinnedMessage.tsx index 1e0fbf93..2eb97951 100644 --- a/src/components/common/messaging/bars/PinnedMessage.tsx +++ b/src/components/common/messaging/bars/PinnedMessage.tsx @@ -308,8 +308,8 @@ export default observer( // if (!last_id) return null; // if (hidden) return null; - - // renderer.messages.slice().reverse().map((res, i) => { + // console.log(renderer.pinned_messages, "PINNED MESSAGES") + // renderer.pinned_messages.slice().reverse().map((res, i) => { // console.log(res, 8989) // }) function truncateText(text: string, chars: number) { @@ -365,7 +365,7 @@ export default observer(
{ - renderer.messages.slice().reverse().map((msg, i) => { + renderer.pinned_messages.slice().reverse().map((msg, i) => { if (msg.is_pinned) { let content = msg.content ? truncateText(msg.content, 220) : "" pinFound = true @@ -413,11 +413,11 @@ export default observer( style={{ display: 'flex', paddingTop: "5px", justifyContent: "center" }}> - + /> */}
} diff --git a/src/lib/renderer/Singleton.ts b/src/lib/renderer/Singleton.ts index 90c4d20d..09aa1f49 100644 --- a/src/lib/renderer/Singleton.ts +++ b/src/lib/renderer/Singleton.ts @@ -15,6 +15,7 @@ export class ChannelRenderer { atTop: Nullable = null; atBottom: Nullable = null; messages: Message[] = []; + pinned_messages: Message[] = []; currentRenderer: RendererRoutines = SimpleRenderer; diff --git a/src/lib/renderer/simple/SimpleRenderer.ts b/src/lib/renderer/simple/SimpleRenderer.ts index 19222589..52d89ec0 100644 --- a/src/lib/renderer/simple/SimpleRenderer.ts +++ b/src/lib/renderer/simple/SimpleRenderer.ts @@ -9,12 +9,14 @@ export const SimpleRenderer: RendererRoutines = { if (nearby) renderer.channel .fetchMessagesWithUsers({ nearby, limit: 100 }) - .then(({ messages }) => { + .then(({ messages, pinned_messages }) => { messages.sort((a, b) => a._id.localeCompare(b._id)); runInAction(() => { renderer.state = "RENDER"; renderer.messages = messages; + renderer.pinned_messages = pinned_messages; + renderer.atTop = false; renderer.atBottom = false; @@ -27,13 +29,12 @@ export const SimpleRenderer: RendererRoutines = { else renderer.channel .fetchMessagesWithUsers({}) - .then(({ messages }) => { - console.log(messages, 9090); + .then(({ messages, pinned_messages }) => { messages.reverse(); - runInAction(() => { renderer.state = "RENDER"; renderer.messages = messages; + renderer.pinned_messages = pinned_messages; renderer.atTop = messages.length < 50; renderer.atBottom = true; From 2e80d727d952b67aaf980621497235584cf4c1ea Mon Sep 17 00:00:00 2001 From: TeamAbronDev Date: Sun, 26 Jan 2025 16:29:46 +0330 Subject: [PATCH 10/14] changed submodule --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 03cd9baa..5d26e0e4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -8,4 +8,4 @@ [submodule "external/revolt.js"] path = external/revolt.js url = https://github.com/archem-team/revolt.js - branch = revite-backports + branch = pin_message From 4dfaa43c15b412102ce2151bbdb99dd61b96b3e6 Mon Sep 17 00:00:00 2001 From: TeamAbronDev Date: Sun, 26 Jan 2025 17:26:25 +0330 Subject: [PATCH 11/14] exclude DirectMessage --- .../common/messaging/bars/PinnedMessage.tsx | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/components/common/messaging/bars/PinnedMessage.tsx b/src/components/common/messaging/bars/PinnedMessage.tsx index 2eb97951..a88a5bef 100644 --- a/src/components/common/messaging/bars/PinnedMessage.tsx +++ b/src/components/common/messaging/bars/PinnedMessage.tsx @@ -325,16 +325,13 @@ export default observer( let pinFound = false return ( <> - -
unhide()} - > - - -
-
- - + {channel.channel_type != "DirectMessage" && ( + +
unhide()}> + +
+
+ )} {!hidden &&
Date: Mon, 27 Jan 2025 16:14:52 +0330 Subject: [PATCH 12/14] emit added --- .../common/messaging/bars/PinnedMessage.tsx | 49 +++++++------------ src/lib/ContextMenus.tsx | 6 ++- src/pages/channels/Channel.tsx | 2 +- 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/components/common/messaging/bars/PinnedMessage.tsx b/src/components/common/messaging/bars/PinnedMessage.tsx index a88a5bef..155cec01 100644 --- a/src/components/common/messaging/bars/PinnedMessage.tsx +++ b/src/components/common/messaging/bars/PinnedMessage.tsx @@ -280,38 +280,28 @@ export default observer( ({ channel }: { channel: Channel; }) => { const [hidden, setHidden] = useState(true); const unhide = () => setHidden(false); - - // useEffect(() => setHidden(false), [last_id]); - // useEffect(() => internalSubscribe("NewMessages", "hide", hide), []); - // useEffect(() => { - // const onKeyDown = (e: KeyboardEvent) => - // e.key === "Escape" && hide(); - - // document.addEventListener("keydown", onKeyDown); - // return () => document.removeEventListener("keydown", onKeyDown); - // }, []); - - // const extendedMessage = new MessageExtendedClass(client); - - - // useEffect(() => { - // if (last_id) { - // try { - // setTimeAgo(dayjs(decodeTime(last_id)).fromNow()); - // } catch (err) { } - // } - // }, [last_id]); - const renderer = getRenderer(channel); + useEffect(() => { + // Subscribe to the update event for pinned messages + const unsubscribe = internalSubscribe( + "PinnedMessage", + "update", + (newMessage: unknown) => { + const message = newMessage as MessageI; + if (!renderer.pinned_messages.find((msg) => msg._id === message._id)) { + renderer.pinned_messages.push(message); + } + } + ); + + // Cleanup subscription on unmount + return () => unsubscribe(); + }, [renderer]); + + + const history = useHistory(); if (renderer.state !== "RENDER") return null; - // if (!last_id) return null; - // if (hidden) return null; - - // console.log(renderer.pinned_messages, "PINNED MESSAGES") - // renderer.pinned_messages.slice().reverse().map((res, i) => { - // console.log(res, 8989) - // }) function truncateText(text: string, chars: number) { if (text.length > chars) { return text.slice(0, chars) + ".."; @@ -321,7 +311,6 @@ export default observer( const client = useClient() - let pinFound = false return ( <> diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index 2812fe1a..b729018e 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -214,14 +214,16 @@ export default function ContextMenus() { const index = messages.findIndex( (x) => x._id === data.message._id, ); - + let message if (index > -1) { message = messages[index]; } - console.log(message,7878) + if (message) { + internalEmit("PinnedMessage", "update", message); + } internalEmit("MessageBox", "pin", message); // data.message.channel?.ack(pin_id, true); diff --git a/src/pages/channels/Channel.tsx b/src/pages/channels/Channel.tsx index 32418e39..3a9d022e 100644 --- a/src/pages/channels/Channel.tsx +++ b/src/pages/channels/Channel.tsx @@ -100,7 +100,7 @@ export const Channel = observer( const client = useClient(); const state = useApplicationState(); - if (!client.channels.exists(id) && server_id) { + if (!client.channels.get(id)) { if (server_id) { const server = client.servers.get(server_id); if (server && server.channel_ids.length > 0) { From e07e784de1d521c5a33bc614005843ead4ea7ba7 Mon Sep 17 00:00:00 2001 From: Abron Date: Mon, 3 Feb 2025 13:59:23 +0330 Subject: [PATCH 13/14] disallowed pin in directmessage --- src/components/common/messaging/bars/PinnedMessage.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/common/messaging/bars/PinnedMessage.tsx b/src/components/common/messaging/bars/PinnedMessage.tsx index 155cec01..89891f9a 100644 --- a/src/components/common/messaging/bars/PinnedMessage.tsx +++ b/src/components/common/messaging/bars/PinnedMessage.tsx @@ -299,7 +299,6 @@ export default observer( }, [renderer]); - const history = useHistory(); if (renderer.state !== "RENDER") return null; function truncateText(text: string, chars: number) { @@ -322,7 +321,7 @@ export default observer( )} {!hidden && -
+
setHidden(true)} style={{ From 7b15dfd3d24d7eacce2cbbad95497730ce94e885 Mon Sep 17 00:00:00 2001 From: Abron Date: Mon, 3 Feb 2025 14:01:11 +0330 Subject: [PATCH 14/14] disallowed pin in directmessage --- src/lib/ContextMenus.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index b729018e..101b359d 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -860,7 +860,7 @@ export default function ContextMenus() { if (sendPermission) { - if (message.is_pinned) { + if (message.is_pinned && channel?.channel_type != "DirectMessage") { generateAction({ action: "unpin_message", channel,