This commit is contained in:
thororen1234 2024-10-14 19:33:17 -04:00
parent 75fac79ad1
commit deceb2ba97
13 changed files with 186 additions and 58 deletions

View file

@ -6,12 +6,14 @@
import "./style.css";
import { definePluginSettings } from "@api/Settings";
import { getUserSettingLazy } from "@api/UserSettings";
import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants";
import { proxyLazy } from "@utils/lazy";
import definePlugin from "@utils/types";
import definePlugin, { OptionType } from "@utils/types";
import { findComponentByCodeLazy } from "@webpack";
import { ChannelStore, Forms, MessageStore, RestAPI, Tooltip, useEffect, useState, useStateFromStores } from "@webpack/common";
import { ChannelStore, Constants, Forms, MessageStore, RestAPI, Tooltip, useEffect, useState, useStateFromStores } from "@webpack/common";
import type { ComponentType, HTMLAttributes } from "react";
declare enum SpinnerTypes {
@ -38,52 +40,124 @@ const { Spinner } = proxyLazy(() => Forms as any as {
SpinnerTypes: typeof SpinnerTypes;
});
const MessageDisplayCompact = getUserSettingLazy("textAndImages", "messageDisplayCompact")!;
const ChannelMessage = findComponentByCodeLazy("isFirstMessageInForumPost", "trackAnnouncementViews") as ComponentType<any>;
const settings = definePluginSettings({
onLink: {
description: "Show tooltip when hovering over message links",
type: OptionType.BOOLEAN,
default: true,
restartNeeded: true,
},
onReply: {
description: "Show tooltip when hovering over message replies",
type: OptionType.BOOLEAN,
default: true,
restartNeeded: true,
},
onForward: {
description: "Show tooltip when hovering over forwarded messages",
type: OptionType.BOOLEAN,
default: true,
restartNeeded: true,
},
display: {
description: "Display style",
type: OptionType.SELECT,
options: [
{
label: "Same as message",
value: "auto",
default: true
},
{
label: "Compact",
value: "compact"
},
{
label: "Cozy",
value: "cozy"
},
]
},
});
export default definePlugin({
name: "MessageLinkTooltip",
description: "Like MessageLinkEmbed but without taking space",
authors: [Devs.Kyuuhachi],
settings,
patches: [
{
find: ',className:"channelMention",children:[',
replacement: {
match: /(?<=\.jsxs\)\()(\i\.\i)(?=,\{role:"link")/,
replace: "$self.wrapComponent(arguments[0], $1)"
}
}
match: /(?<=\.jsxs\)\()(\i\.\i),\{(?=role:"link")/,
replace: "$self.MentionTooltip,{Component:$1,vcProps:arguments[0],"
},
predicate: () => settings.store.onLink,
},
{
find: "Messages.REPLY_QUOTE_MESSAGE_NOT_LOADED",
replacement: {
// Should match two places
match: /(\i\.Clickable),\{/g,
replace: "$self.ReplyTooltip,{Component:$1,vcProps:arguments[0],"
},
predicate: () => settings.store.onReply,
},
{
find: "Messages.MESSAGE_FORWARDED}",
replacement: {
match: /(\i\.Clickable),\{/,
replace: "$self.ForwardTooltip,{Component:$1,vcProps:arguments[0],"
},
predicate: () => settings.store.onForward,
},
],
wrapComponent({ messageId, channelId }, Component: ComponentType) {
return props => {
if (messageId === undefined) return <Component {...props} />;
return <Tooltip
tooltipClassName="c98-message-link-tooltip"
text={
<ErrorBoundary>
<MessagePreview
channelId={channelId}
messageId={messageId}
/>
</ErrorBoundary>
}
>
{({ onMouseEnter, onMouseLeave }) =>
<Component
{...props}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
/>
}
</Tooltip>;
};
}
MentionTooltip({ Component, vcProps, ...props }) {
return withTooltip(Component, props, vcProps.messageId, vcProps.channelId);
},
ReplyTooltip({ Component, vcProps, ...props }) {
const mess = vcProps.baseMessage.messageReference;
return withTooltip(Component, props, mess?.message_id, mess?.channel_id);
},
ForwardTooltip({ Component, vcProps, ...props }) {
const mess = vcProps.message.messageReference;
return withTooltip(Component, props, mess?.message_id, mess?.channel_id);
},
});
function withTooltip(Component, props, messageId, channelId) {
if (!messageId) return <Component {...props} />;
return <Tooltip
tooltipClassName="c98-message-link-tooltip"
text={
<ErrorBoundary>
<MessagePreview
channelId={channelId}
messageId={messageId}
/>
</ErrorBoundary>
}
children={({ onMouseEnter, onMouseLeave }) =>
<Component {...props} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />}
/>;
}
function MessagePreview({ channelId, messageId }) {
const channel = ChannelStore.getChannel(channelId);
const message = useMessage(channelId, messageId);
const rawCompact = MessageDisplayCompact.useSetting();
const compact = settings.store.display === "compact" ? true : settings.store.display === "cozy" ? false : rawCompact;
// TODO handle load failure
if (!message) {
return <Spinner type={Spinner.Type.PULSING_ELLIPSIS} />;
@ -94,6 +168,7 @@ function MessagePreview({ channelId, messageId }) {
message={message}
channel={channel}
subscribeToComponentDispatch={false}
compact={compact}
/>;
}
@ -107,7 +182,7 @@ function useMessage(channelId, messageId) {
if (message == null)
(async () => {
const res = await RestAPI.get({
url: `/channels/${channelId}/messages`,
url: Constants.Endpoints.MESSAGES(channelId),
query: {
limit: 1,
around: messageId,