mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-01-09 09:26:22 +00:00
Merge branch 'dev' into update-dependencies-eslint
This commit is contained in:
commit
0d3c562573
13 changed files with 142 additions and 46 deletions
|
@ -28,7 +28,7 @@ interface Props<T = any> {
|
|||
/** Render nothing if an error occurs */
|
||||
noop?: boolean;
|
||||
/** Fallback component to render if an error occurs */
|
||||
fallback?: React.ComponentType<React.PropsWithChildren<{ error: any; message: string; stack: string; }>>;
|
||||
fallback?: React.ComponentType<React.PropsWithChildren<{ error: any; message: string; stack: string; wrappedProps: T; }>>;
|
||||
/** called when an error occurs. The props property is only available if using .wrap */
|
||||
onError?(data: { error: Error, errorInfo: React.ErrorInfo, props: T; }): void;
|
||||
/** Custom error message */
|
||||
|
@ -82,7 +82,10 @@ const ErrorBoundary = LazyComponent(() => {
|
|||
|
||||
if (this.props.fallback)
|
||||
return (
|
||||
<this.props.fallback {...this.state}>
|
||||
<this.props.fallback
|
||||
wrappedProps={this.props.wrappedProps}
|
||||
{...this.state}
|
||||
>
|
||||
{this.props.children}
|
||||
</this.props.fallback>
|
||||
);
|
||||
|
|
|
@ -85,7 +85,7 @@ export default definePlugin({
|
|||
replace: "$&onRequestClose:$self.onPopoutClose,"
|
||||
},
|
||||
{
|
||||
match: /(?<=.avatarWrapper,)/,
|
||||
match: /(?<=\.avatarWrapper,)/,
|
||||
replace: "ref:$self.accountPanelRef,onContextMenu:$self.openAccountPanelContextMenu,"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -20,6 +20,7 @@ import { Devs } from "@utils/constants";
|
|||
import { getCurrentChannel, getCurrentGuild } from "@utils/discord";
|
||||
import { runtimeHashMessageKey } from "@utils/intlHash";
|
||||
import { SYM_LAZY_CACHED, SYM_LAZY_GET } from "@utils/lazy";
|
||||
import { ModalAPI } from "@utils/modal";
|
||||
import { relaunch } from "@utils/native";
|
||||
import { canonicalizeMatch, canonicalizeReplace, canonicalizeReplacement } from "@utils/patches";
|
||||
import definePlugin, { PluginNative, StartAt } from "@utils/types";
|
||||
|
@ -147,6 +148,8 @@ function makeShortcuts() {
|
|||
me: { getter: () => Common.UserStore.getCurrentUser(), preload: false },
|
||||
meId: { getter: () => Common.UserStore.getCurrentUser().id, preload: false },
|
||||
messages: { getter: () => Common.MessageStore.getMessages(Common.SelectedChannelStore.getChannelId()), preload: false },
|
||||
openModal: { getter: () => ModalAPI.openModal },
|
||||
openModalLazy: { getter: () => ModalAPI.openModalLazy },
|
||||
|
||||
Stores: {
|
||||
getter: () => Object.fromEntries(
|
||||
|
|
9
src/plugins/fullUserInChatbox/README.md
Normal file
9
src/plugins/fullUserInChatbox/README.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Full User In Chatbox
|
||||
|
||||
Adds the full user mention to the textbox
|
||||
|
||||
Adds the avatar if you have mentioned avatars enabled
|
||||
|
||||
Provides the full context menu to make it easy to access the users profile, and other common actions
|
||||
|
||||
https://github.com/user-attachments/assets/cd9edb33-99c8-4c8d-b669-8cddd05f4b45
|
47
src/plugins/fullUserInChatbox/index.tsx
Normal file
47
src/plugins/fullUserInChatbox/index.tsx
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin from "@utils/types";
|
||||
import { findComponentByCodeLazy } from "@webpack";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
const UserMentionComponent = findComponentByCodeLazy(".USER_MENTION)");
|
||||
|
||||
interface UserMentionComponentProps {
|
||||
id: string;
|
||||
channelId: string;
|
||||
guildId: string;
|
||||
OriginalComponent: ReactNode;
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "FullUserInChatbox",
|
||||
description: "Makes the user mention in the chatbox have more functionalities, like left/right clicking",
|
||||
authors: [Devs.sadan],
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: ':"text":',
|
||||
replacement: {
|
||||
match: /(hidePersonalInformation\).+?)(if\(null!=\i\){.+?return \i)(?=})/,
|
||||
replace: "$1return $self.UserMentionComponent({...arguments[0],OriginalComponent:(()=>{$2})()});"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
UserMentionComponent: ErrorBoundary.wrap((props: UserMentionComponentProps) => (
|
||||
<UserMentionComponent
|
||||
// This seems to be constant
|
||||
className="mention"
|
||||
userId={props.id}
|
||||
channelId={props.channelId}
|
||||
/>
|
||||
), {
|
||||
fallback: ({ wrappedProps }) => wrappedProps.OriginalComponent
|
||||
})
|
||||
});
|
5
src/plugins/noUnblockToJump/README.md
Normal file
5
src/plugins/noUnblockToJump/README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# No Unblock To Jump
|
||||
|
||||
Removes the popup preventing you to jump to a message from a blocked/ignored user (eg: in search results)
|
||||
|
||||
![A modal popup telling you to unblock a user to jump their message](https://github.com/user-attachments/assets/0e4b859d-f3b3-4101-9a83-829afb473d1e)
|
|
@ -26,25 +26,46 @@ export default definePlugin({
|
|||
authors: [Devs.dzshn],
|
||||
patches: [
|
||||
{
|
||||
// Clicking on search results to jump
|
||||
find: '.id,"Search Results"',
|
||||
replacement: {
|
||||
match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/,
|
||||
replace: "if(false)$1"
|
||||
}
|
||||
replacement: [
|
||||
{
|
||||
match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/,
|
||||
replace: "if(false)$1"
|
||||
},
|
||||
{
|
||||
match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}#{intl::UNIGNORE_TO_JUMP_TITLE})/,
|
||||
replace: "if(false)$1"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
// Jump buttton in top right corner of messages
|
||||
find: "renderJumpButton()",
|
||||
replacement: {
|
||||
match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/,
|
||||
replace: "if(false)$1"
|
||||
}
|
||||
replacement: [
|
||||
{
|
||||
match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/,
|
||||
replace: "if(false)$1"
|
||||
},
|
||||
{
|
||||
match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}#{intl::UNIGNORE_TO_JUMP_TITLE})/,
|
||||
replace: "if(false)$1"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
// Clicking on replied messages to jump
|
||||
find: "flash:!0,returnMessageId",
|
||||
replacement: {
|
||||
match: /.\?(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/,
|
||||
replace: "false?$1"
|
||||
}
|
||||
replacement: [
|
||||
{
|
||||
match: /.\?(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/,
|
||||
replace: "false?$1"
|
||||
},
|
||||
{
|
||||
match: /.\?(.{1,10}\.show\({.{1,50}#{intl::UNIGNORE_TO_JUMP_TITLE})/,
|
||||
replace: "false?$1"
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
|
@ -57,7 +57,7 @@ const UrlReplacementRules: Record<string, URLReplacementRule> = {
|
|||
description: "Open Tidal links in the Tidal app",
|
||||
},
|
||||
itunes: {
|
||||
match: /^https:\/\/music\.apple\.com\/([a-z]{2}\/)?(album|artist|playlist|song|curator)\/([^/?#]+)\/?([^/?#]+)?(?:\?.*)?(?:#.*)?$/,
|
||||
match: /^https:\/\/(?:geo\.)?music\.apple\.com\/([a-z]{2}\/)?(album|artist|playlist|song|curator)\/([^/?#]+)\/?([^/?#]+)?(?:\?.*)?(?:#.*)?$/,
|
||||
replace: (_, lang, type, name, id) => id ? `itunes://music.apple.com/us/${type}/${name}/${id}` : `itunes://music.apple.com/us/${type}/${name}`,
|
||||
description: "Open Apple Music links in the iTunes app"
|
||||
},
|
||||
|
|
|
@ -30,13 +30,13 @@ export default definePlugin({
|
|||
{
|
||||
find: ".removeMosaicItemHoverButton),",
|
||||
replacement: {
|
||||
match: /\.nonMediaMosaicItem\]:.{0,40}children:\[(?<=showDownload:(\i).+?isVisualMediaType:(\i).+?)/,
|
||||
replace: "$&$1&&$2&&$self.renderPiPButton(),"
|
||||
match: /\.nonMediaMosaicItem\]:.{0,40}children:\i.slice\(\i\)(?<=showDownload:(\i).+?isVisualMediaType:(\i).+?)/,
|
||||
replace: (m, showDownload, isVisualMediaType) => `${m}.unshift(${showDownload}&&${isVisualMediaType}&&$self.PictureInPictureButton())`
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
renderPiPButton: ErrorBoundary.wrap(() => {
|
||||
PictureInPictureButton: ErrorBoundary.wrap(() => {
|
||||
return (
|
||||
<Tooltip text="Toggle Picture in Picture">
|
||||
{tooltipProps => (
|
||||
|
|
|
@ -20,7 +20,7 @@ import { definePluginSettings, Settings } from "@api/Settings";
|
|||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import { ChannelStore, FluxDispatcher as Dispatcher, MessageStore, PermissionsBits, PermissionStore, SelectedChannelStore, UserStore } from "@webpack/common";
|
||||
import { ChannelStore, ComponentDispatch, FluxDispatcher as Dispatcher, MessageStore, PermissionsBits, PermissionStore, SelectedChannelStore, UserStore } from "@webpack/common";
|
||||
import { Message } from "discord-types/general";
|
||||
|
||||
const Kangaroo = findByPropsLazy("jumpToMessage");
|
||||
|
@ -60,24 +60,24 @@ export default definePlugin({
|
|||
settings,
|
||||
|
||||
start() {
|
||||
Dispatcher.subscribe("DELETE_PENDING_REPLY", onDeletePendingReply);
|
||||
Dispatcher.subscribe("MESSAGE_END_EDIT", onEndEdit);
|
||||
Dispatcher.subscribe("MESSAGE_START_EDIT", onStartEdit);
|
||||
Dispatcher.subscribe("CREATE_PENDING_REPLY", onCreatePendingReply);
|
||||
document.addEventListener("keydown", onKeydown);
|
||||
},
|
||||
|
||||
stop() {
|
||||
Dispatcher.unsubscribe("DELETE_PENDING_REPLY", onDeletePendingReply);
|
||||
Dispatcher.unsubscribe("MESSAGE_END_EDIT", onEndEdit);
|
||||
Dispatcher.unsubscribe("MESSAGE_START_EDIT", onStartEdit);
|
||||
Dispatcher.unsubscribe("CREATE_PENDING_REPLY", onCreatePendingReply);
|
||||
document.removeEventListener("keydown", onKeydown);
|
||||
},
|
||||
});
|
||||
|
||||
const onDeletePendingReply = () => replyIdx = -1;
|
||||
const onEndEdit = () => editIdx = -1;
|
||||
flux: {
|
||||
DELETE_PENDING_REPLY() {
|
||||
replyIdx = -1;
|
||||
},
|
||||
MESSAGE_END_EDIT() {
|
||||
editIdx = -1;
|
||||
},
|
||||
MESSAGE_START_EDIT: onStartEdit,
|
||||
CREATE_PENDING_REPLY: onCreatePendingReply
|
||||
}
|
||||
});
|
||||
|
||||
function calculateIdx(messages: Message[], id: string) {
|
||||
const idx = messages.findIndex(m => m.id === id);
|
||||
|
@ -109,6 +109,8 @@ function onKeydown(e: KeyboardEvent) {
|
|||
if (!isUp && e.key !== "ArrowDown") return;
|
||||
if (!isCtrl(e) || isAltOrMeta(e)) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if (e.shiftKey)
|
||||
nextEdit(isUp);
|
||||
else
|
||||
|
@ -194,9 +196,10 @@ function nextReply(isUp: boolean) {
|
|||
channel,
|
||||
message,
|
||||
shouldMention: shouldMention(message),
|
||||
showMentionToggle: channel.guild_id !== null && message.author.id !== meId,
|
||||
showMentionToggle: channel.isPrivate() && message.author.id !== meId,
|
||||
_isQuickReply: true
|
||||
});
|
||||
ComponentDispatch.dispatchToLastSubscribed("TEXTAREA_FOCUS");
|
||||
jumpIfOffScreen(channel.id, message.id);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
import "./spotifyStyles.css";
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { Flex } from "@components/Flex";
|
||||
import { ImageIcon, LinkIcon, OpenExternalIcon } from "@components/Icons";
|
||||
import { debounce } from "@shared/debounce";
|
||||
|
@ -130,7 +131,9 @@ function Controls() {
|
|||
>
|
||||
<Shuffle />
|
||||
</Button>
|
||||
<Button onClick={() => SpotifyStore.prev()}>
|
||||
<Button onClick={() => {
|
||||
Settings.plugins.SpotifyControls.previousButtonRestartsTrack && SpotifyStore.position > 3000 ? SpotifyStore.seek(0) : SpotifyStore.prev();
|
||||
}}>
|
||||
<SkipPrev />
|
||||
</Button>
|
||||
<Button onClick={() => SpotifyStore.setPlaying(!isPlaying)}>
|
||||
|
|
|
@ -44,6 +44,11 @@ export default definePlugin({
|
|||
type: OptionType.BOOLEAN,
|
||||
description: "Open Spotify URIs instead of Spotify URLs. Will only work if you have Spotify installed and might not work on all platforms",
|
||||
default: false
|
||||
},
|
||||
previousButtonRestartsTrack: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Restart currently playing track when pressing the previous button if playtime is >3s",
|
||||
default: true
|
||||
}
|
||||
},
|
||||
patches: [
|
||||
|
|
|
@ -141,35 +141,32 @@ export const ModalContent = LazyComponent(() => Modals.ModalContent);
|
|||
export const ModalFooter = LazyComponent(() => Modals.ModalFooter);
|
||||
export const ModalCloseButton = LazyComponent(() => Modals.ModalCloseButton);
|
||||
|
||||
const ModalAPI = findByPropsLazy("openModalLazy");
|
||||
export const ModalAPI = findByPropsLazy("openModalLazy");
|
||||
|
||||
/**
|
||||
* Wait for the render promise to resolve, then open a modal with it.
|
||||
* This is equivalent to render().then(openModal)
|
||||
* You should use the Modal components exported by this file
|
||||
*/
|
||||
export function openModalLazy(render: () => Promise<RenderFunction>, options?: ModalOptions & { contextKey?: string; }): Promise<string> {
|
||||
return ModalAPI.openModalLazy(render, options);
|
||||
}
|
||||
export const openModalLazy: (render: () => Promise<RenderFunction>, options?: ModalOptions & { contextKey?: string; }) => Promise<string>
|
||||
= proxyLazyWebpack(() => ModalAPI.openModalLazy);
|
||||
|
||||
/**
|
||||
* Open a Modal with the given render function.
|
||||
* You should use the Modal components exported by this file
|
||||
*/
|
||||
export function openModal(render: RenderFunction, options?: ModalOptions, contextKey?: string): string {
|
||||
return ModalAPI.openModal(render, options, contextKey);
|
||||
}
|
||||
export const openModal: (render: RenderFunction, options?: ModalOptions, contextKey?: string) => string
|
||||
= proxyLazyWebpack(() => ModalAPI.openModal);
|
||||
|
||||
/**
|
||||
* Close a modal by its key
|
||||
*/
|
||||
export function closeModal(modalKey: string, contextKey?: string): void {
|
||||
return ModalAPI.closeModal(modalKey, contextKey);
|
||||
}
|
||||
export const closeModal: (modalKey: string, contextKey?: string) => void
|
||||
= proxyLazyWebpack(() => ModalAPI.closeModal);
|
||||
|
||||
/**
|
||||
* Close all open modals
|
||||
*/
|
||||
export function closeAllModals(): void {
|
||||
return ModalAPI.closeAllModals();
|
||||
}
|
||||
export const closeAllModals: () => void
|
||||
= proxyLazyWebpack(() => ModalAPI.closeAllModals);
|
||||
|
||||
|
|
Loading…
Reference in a new issue