Add pin message
parent
c1771da8cc
commit
e3f5a01f2e
|
|
@ -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) => {
|
|||
</Base>
|
||||
);
|
||||
}
|
||||
console.log(channel)
|
||||
if (!channel.havePermission("SendMessage") && channel.recipient?.relationship == "Blocked" || channel.recipient?.relationship == "BlockedOther"){
|
||||
return (
|
||||
<Base>
|
||||
<Blocked>
|
||||
<Action>
|
||||
<PermissionTooltip
|
||||
permission="SendMessages"
|
||||
placement="top">
|
||||
<ShieldX size={22} />
|
||||
</PermissionTooltip>
|
||||
</Action>
|
||||
<div className="text">
|
||||
<Text id="app.main.channel.misc.no_sending" />
|
||||
</div>
|
||||
</Blocked>
|
||||
</Base>
|
||||
);
|
||||
}
|
||||
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 (
|
||||
<Base>
|
||||
<Blocked>
|
||||
<Action>
|
||||
<PermissionTooltip
|
||||
permission="SendMessages"
|
||||
placement="top">
|
||||
<ShieldX size={22} />
|
||||
</PermissionTooltip>
|
||||
</Action>
|
||||
<div className="text">
|
||||
<Text id="app.main.channel.misc.no_sending" />
|
||||
</div>
|
||||
</Blocked>
|
||||
</Base>
|
||||
);
|
||||
}
|
||||
// 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) => {
|
|||
</FloatingLayer>
|
||||
<Base>
|
||||
{/* {channel.havePermission("UploadFiles") ? ( */}
|
||||
<FileAction>
|
||||
<FileUploader
|
||||
size={24}
|
||||
behaviour="multi"
|
||||
style="attachment"
|
||||
fileType="attachments"
|
||||
maxFileSize={20_000_000}
|
||||
attached={uploadState.type !== "none"}
|
||||
uploading={
|
||||
uploadState.type === "uploading" ||
|
||||
uploadState.type === "sending"
|
||||
}
|
||||
remove={async () =>
|
||||
setUploadState({ type: "none" })
|
||||
}
|
||||
onChange={(files) =>
|
||||
setUploadState({ type: "attached", files })
|
||||
}
|
||||
cancel={() =>
|
||||
uploadState.type === "uploading" &&
|
||||
uploadState.cancel.cancel("cancel")
|
||||
}
|
||||
append={(files) => {
|
||||
if (files.length === 0) return;
|
||||
<FileAction>
|
||||
<FileUploader
|
||||
size={24}
|
||||
behaviour="multi"
|
||||
style="attachment"
|
||||
fileType="attachments"
|
||||
maxFileSize={20_000_000}
|
||||
attached={uploadState.type !== "none"}
|
||||
uploading={
|
||||
uploadState.type === "uploading" ||
|
||||
uploadState.type === "sending"
|
||||
}
|
||||
remove={async () =>
|
||||
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],
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</FileAction>
|
||||
if (uploadState.type === "none") {
|
||||
setUploadState({ type: "attached", files });
|
||||
} else if (uploadState.type === "attached") {
|
||||
setUploadState({
|
||||
type: "attached",
|
||||
files: [...uploadState.files, ...files],
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</FileAction>
|
||||
{/* ) : (
|
||||
<ThisCodeWillBeReplacedAnywaysSoIMightAsWellJustDoItThisWay__Padding />
|
||||
)} */}
|
||||
|
|
@ -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" ||
|
||||
|
|
|
|||
|
|
@ -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 = (
|
||||
<div
|
||||
onClick={() => {
|
||||
if (channel.channel_type === "TextChannel") {
|
||||
history.push(
|
||||
`/server/${channel.server_id}/channel/${channel._id}/${data.id}`,
|
||||
);
|
||||
} else {
|
||||
history.push(`/channel/${channel._id}/${data.id}`);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<TextReact
|
||||
id={`app.main.channel.system.message_pinned`}
|
||||
fields={{
|
||||
user: userName,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (data.type as string == "message_unpinned") {
|
||||
children = children = (
|
||||
<div
|
||||
onClick={() => {
|
||||
if (channel.channel_type === "TextChannel") {
|
||||
history.push(
|
||||
`/server/${channel.server_id}/channel/${channel._id}/${data.id}`,
|
||||
);
|
||||
} else {
|
||||
history.push(`/channel/${channel._id}/${data.id}`);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<TextReact
|
||||
id={`app.main.channel.system.message_unpinned`}
|
||||
fields={{
|
||||
user: userName,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<MessageBase highlight={highlight}>
|
||||
|
||||
|
||||
{!hideInfo && (
|
||||
<MessageInfo click={false}>
|
||||
<MessageDetail message={message} position="left" />
|
||||
{/* <SystemMessageIcon className="systemIcon" /> */}
|
||||
</MessageInfo>
|
||||
)}
|
||||
|
||||
|
||||
<SystemContent style={{ height: 20, fontSize: 12, display: "block", width: "100%", textAlign: "center", cursor: "pointer" }}>{children}</SystemContent>
|
||||
</MessageBase>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
@ -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 (
|
||||
<>
|
||||
<PinIcon position="top" accent>
|
||||
<div
|
||||
onClick={() => unhide()}
|
||||
>
|
||||
|
||||
<Pin size={24} />
|
||||
</div>
|
||||
</PinIcon>
|
||||
|
||||
|
||||
{!hidden && <PinBar accent position="top" >
|
||||
<div>
|
||||
<div
|
||||
onClick={() => setHidden(true)}
|
||||
style={{
|
||||
backgroundColor: "var(--block)",
|
||||
width: "100%",
|
||||
position: "sticky",
|
||||
top: "0px",
|
||||
display: "flex",
|
||||
|
||||
justifyContent: "space-between",
|
||||
borderRadius: "5px",
|
||||
padding: "8px 8px"
|
||||
|
||||
}}>
|
||||
|
||||
<LeftArrowAlt size={20} onClick={() => setHidden(true)} />
|
||||
|
||||
<Text
|
||||
id="app.main.channel.misc.pinned_message_title"
|
||||
/>
|
||||
<Pin size={20} />
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div style={{ display: 'grid', flexDirection: "column" }} >
|
||||
{
|
||||
|
||||
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 (
|
||||
|
||||
<div
|
||||
|
||||
onClick={() => {
|
||||
// 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" }}>
|
||||
<>. {" "}</>
|
||||
<Text
|
||||
|
||||
id="app.main.channel.misc.pinned_message"
|
||||
fields={{
|
||||
message_summery: content,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
{!renderer.atTop && <div
|
||||
|
||||
onClick={() => {
|
||||
// setHidden(true);
|
||||
renderer.loadTop()
|
||||
}}
|
||||
|
||||
|
||||
style={{ display: 'flex', paddingTop: "5px", justifyContent: "center" }}>
|
||||
|
||||
<Text
|
||||
|
||||
id="app.main.channel.misc.pinned_load_more"
|
||||
|
||||
/>
|
||||
</div>}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</PinBar>}
|
||||
</>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
@ -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"
|
||||
) : (
|
||||
<Text
|
||||
id={`app.context_menu.${
|
||||
locale ?? action.action
|
||||
}`}
|
||||
id={`app.context_menu.${locale ?? action.action
|
||||
}`}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
|
|
@ -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",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ export const SimpleRenderer: RendererRoutines = {
|
|||
renderer.channel
|
||||
.fetchMessagesWithUsers({})
|
||||
.then(({ messages }) => {
|
||||
console.log(messages, 9090);
|
||||
messages.reverse();
|
||||
|
||||
runInAction(() => {
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<Redirect
|
||||
to={`/server/${server_id}/channel/${target_id}`}
|
||||
|
|
@ -188,6 +189,7 @@ const TextChannel = observer(({ channel }: { channel: ChannelI }) => {
|
|||
<ErrorBoundary section="renderer">
|
||||
<ChannelContent>
|
||||
<NewMessages channel={channel} last_id={lastId} />
|
||||
<PinnedMessage channel={channel} />
|
||||
<MessageArea channel={channel} last_id={lastId} />
|
||||
<TypingIndicator channel={channel} />
|
||||
<JumpToBottom channel={channel} />
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
<PinMessageBox
|
||||
key={message._id}
|
||||
message={message}
|
||||
attachContext
|
||||
channel={renderer.channel}
|
||||
highlight={highlight === message._id}
|
||||
/>
|
||||
,
|
||||
);
|
||||
} else if (message.author_id === "00000000000000000000000000") {
|
||||
render.push(
|
||||
<SystemMessage
|
||||
key={message._id}
|
||||
|
|
@ -171,7 +186,7 @@ export default observer(({ last_id, renderer, highlight }: Props) => {
|
|||
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(
|
||||
<Message
|
||||
message={
|
||||
|
|
|
|||
129
yarn.lock
129
yarn.lock
|
|
@ -1841,6 +1841,13 @@ __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"
|
||||
|
|
@ -5028,23 +5035,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"follow-redirects@npm:^1.14.0":
|
||||
version: 1.14.4
|
||||
resolution: "follow-redirects@npm:1.14.4"
|
||||
"follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.8":
|
||||
version: 1.15.9
|
||||
resolution: "follow-redirects@npm:1.15.9"
|
||||
peerDependenciesMeta:
|
||||
debug:
|
||||
optional: true
|
||||
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
|
||||
checksum: 859e2bacc7a54506f2bf9aacb10d165df78c8c1b0ceb8023f966621b233717dab56e8d08baadc3ad3b9db58af290413d585c999694b7c146aaf2616340c3d2a6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
@ -7056,7 +7053,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:
|
||||
|
|
@ -7071,10 +7068,25 @@ __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.3.2
|
||||
resolution: "mobx@npm:6.3.2"
|
||||
checksum: da853901ddd9bc5347f778b1aebfcbf5215d0cb0909fa17a9580dec2915b034b385e8cea6f2a85bd917078a29fcbb129c28be10e61db06c59bd3c94ace15f4a9
|
||||
version: 6.13.5
|
||||
resolution: "mobx@npm:6.13.5"
|
||||
checksum: 2a253e505900169326873b573660dab58ce8284a435c75d77775a665af9eed623c1976a5eab3cfb53561cac4713f70194f49a2b8e4111419a2e4291f51e5485a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
@ -7279,18 +7291,18 @@ __metadata:
|
|||
linkType: hard
|
||||
|
||||
"openapi-typescript@npm:^5.2.0":
|
||||
version: 5.2.0
|
||||
resolution: "openapi-typescript@npm:5.2.0"
|
||||
version: 5.4.2
|
||||
resolution: "openapi-typescript@npm:5.4.2"
|
||||
dependencies:
|
||||
js-yaml: ^4.1.0
|
||||
mime: ^3.0.0
|
||||
prettier: ^2.5.1
|
||||
prettier: ^2.6.2
|
||||
tiny-glob: ^0.2.9
|
||||
undici: ^4.14.1
|
||||
yargs-parser: ^21.0.0
|
||||
undici: ^5.4.0
|
||||
yargs-parser: ^21.0.1
|
||||
bin:
|
||||
openapi-typescript: bin/cli.js
|
||||
checksum: 193b0d910d1c067dcbb0f079bf2ae29a3bd392cbae82265760e6e96a70221a3d8d7c287c77af845c2b4bfd4c04251f800c838c63a76564e9f1427b47e62fb598
|
||||
checksum: 7777dfc99dff8971cdfa9c9d965ee6f464fd58ec81ee1add1450c354d7ca09fa48d5aacef27624a203e627cda375fc039516f9fbb2afdf6911b631329fc814a5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
@ -7508,12 +7520,12 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prettier@npm:^2.5.1":
|
||||
version: 2.6.2
|
||||
resolution: "prettier@npm:2.6.2"
|
||||
"prettier@npm:^2.6.2":
|
||||
version: 2.8.8
|
||||
resolution: "prettier@npm:2.8.8"
|
||||
bin:
|
||||
prettier: bin-prettier.js
|
||||
checksum: 48d08dde8e9fb1f5bccdd205baa7f192e9fc8bc98f86e1b97d919de804e28c806b0e6cc685e4a88211aa7987fa9668f30baae19580d87ced3ed0f2ec6572106f
|
||||
checksum: b49e409431bf129dd89238d64299ba80717b57ff5a6d1c1a8b1a28b590d998a34e083fa13573bc732bb8d2305becb4c9a4407f8486c81fa7d55100eb08263cf8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
@ -7637,7 +7649,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:
|
||||
|
|
@ -7649,6 +7661,18 @@ __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"
|
||||
|
|
@ -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<compat/typescript>":
|
||||
version: 4.6.4
|
||||
resolution: "typescript@patch:typescript@npm%3A4.6.4#~builtin<compat/typescript>::version=4.6.4&hash=bda367"
|
||||
version: 4.9.5
|
||||
resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin<compat/typescript>::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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue