Merge branch 'dev'

This commit is contained in:
thororen 2024-08-27 12:31:38 -04:00
commit 549ff6db68
8 changed files with 79 additions and 91 deletions

View file

@ -1,25 +1,14 @@
# Equicord # Equicord [<img src="./browser/icon.png" width="225" align="left" alt="Equicord">](https://github.com/Equicord/Equicord)
An enhanced version of [Vencord](https://github.com/Vendicated/Vencord) by [Vendicated](https://github.com/Vendicated) called Equicord. [![Equibop](https://img.shields.io/badge/Equibop-grey?style=flat)](https://github.com/Equicord/Equibop)
[![Tests](https://github.com/Equicord/Equicord/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/Equicord/Equicord/actions/workflows/test.yml)
[![Discord](https://img.shields.io/discord/1207691698386501634.svg?color=768AD4&label=Discord&logo=discord&logoColor=white)](https://discord.gg/VasF3Ma4Ab)
![image](https://github.com/Equicord/Equicord/assets/78185467/81707ad9-3a04-4f76-88a0-60ee70684f81) Equicord is a fork of [Vencord](https://github.com/Vendicated/Vencord), with over 300+ plugins.
## Features You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, changes, chat or even support.<br><br></br>
- Third-party plugins implemented into the main build.
- 100+ plugins built-in.
- Some highlights: SpotifyControls, MessageLogger, Experiments, GameActivityToggle, Translate, NoTrack, QuickReply, Free Emotes/Stickers, PermissionsViewer,
CustomCommands, ShowHiddenChannels, PronounDB
- Fairly lightweight despite the many inbuilt plugins
- Works on any Discord branch: Stable, Canary or PTB all work (though for the best experience, I recommend stable!)
- Custom CSS and Themes: Inbuilt CSS editor with support to import any CSS files (including BetterDiscord themes)
- Privacy friendly, blocks Discord analytics & crash reporting out of the box and has no telemetry
- Maintained very actively, broken plugins are usually fixed within 12 hours
- Able to update inside of Equicord through the update tab.
- Same supporter badges as on Vencord (Don't lose your benefits)
- Easy to install third-party plugins through the plugin page in Discord.
- Request for plugins from Discord.
### Extra included plugins
<details> <details>
<summary>Extra included plugins (123 additional plugins)</summary> <summary>Extra included plugins (123 additional plugins)</summary>
@ -200,17 +189,10 @@ Inject Equicord into your client:
```shell ```shell
pnpm inject pnpm inject
``` ```
After you have done this command, it will look like you are just installing Equicord but it will say it is a development build. If it doesn't say it is a development build, please reach out for support in the [Discord Server](https://discord.gg/5Xh2W87egW)
## Join our Support/Community Server
https://discord.gg/5Xh2W87egW
## Credits ## Credits
Thank you to [Vendicated](https://github.com/Vendicated) for creating [Vencord](https://github.com/Vendicated/Vencord). Thank you to [Vendicated](https://github.com/Vendicated) for creating [Vencord](https://github.com/Vendicated/Vencord) & [Suncord](https://github.com/verticalsync/Suncord) by [verticalsync](https://github.com/verticalsync) for helping when needed.
Thank you to [Suncord [EOL]](https://github.com/verticalsync/Suncord) by [VerticalSync](https://github.com/verticalsync) for helping me when needed.
## Star History ## Star History

View file

@ -158,7 +158,7 @@ export default definePlugin({
const progress = quest.config.configVersion === 1 ? data.userStatus.streamProgressSeconds : Math.floor(data.userStatus.progress.PLAY_ON_DESKTOP.value); const progress = quest.config.configVersion === 1 ? data.userStatus.streamProgressSeconds : Math.floor(data.userStatus.progress.PLAY_ON_DESKTOP.value);
showNotification({ showNotification({
title: `${applicationName} - Quests Completer`, title: `${applicationName} - Quests Completer`,
body: `Current progress: ${progress}/${secondsNeeded} minutes.`, body: `Current progress: ${progress}/${secondsNeeded} seconds.`,
icon: icon, icon: icon,
}); });
@ -191,7 +191,7 @@ export default definePlugin({
const progress = quest.config.configVersion === 1 ? data.userStatus.streamProgressSeconds : Math.floor(data.userStatus.progress.STREAM_ON_DESKTOP.value); const progress = quest.config.configVersion === 1 ? data.userStatus.streamProgressSeconds : Math.floor(data.userStatus.progress.STREAM_ON_DESKTOP.value);
showNotification({ showNotification({
title: `${applicationName} - Quests Completer`, title: `${applicationName} - Quests Completer`,
body: `Current progress: ${progress}/${secondsNeeded} minutes.`, body: `Current progress: ${progress}/${secondsNeeded} seconds.`,
icon: icon, icon: icon,
}); });

View file

@ -8,7 +8,7 @@ import "./styles.css";
import { NavContextMenuPatchCallback } from "@api/ContextMenu"; import { NavContextMenuPatchCallback } from "@api/ContextMenu";
import * as DataStore from "@api/DataStore"; import * as DataStore from "@api/DataStore";
import { definePluginSettings } from "@api/Settings"; import { definePluginSettings, migratePluginSettings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary"; import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { openModal } from "@utils/modal"; import { openModal } from "@utils/modal";
@ -18,6 +18,7 @@ import { i18n, Menu, Tooltip, useEffect, useState } from "@webpack/common";
import { Message, User } from "discord-types/general"; import { Message, User } from "discord-types/general";
import { SetTimezoneModal } from "./TimezoneModal"; import { SetTimezoneModal } from "./TimezoneModal";
import { migrateData } from "plugins/pinDms/data";
export const DATASTORE_KEY = "vencord-timezones"; export const DATASTORE_KEY = "vencord-timezones";
@ -137,9 +138,9 @@ const userContextMenuPatch: NavContextMenuPatchCallback = (children, { user }: {
}; };
migratePluginSettings("Timezones", "Timezone");
export default definePlugin({ export default definePlugin({
name: "Timezone", name: "Timezones",
authors: [Devs.Aria], authors: [Devs.Aria],
description: "Shows the local time of users in profiles and message headers", description: "Shows the local time of users in profiles and message headers",
contextMenus: { contextMenus: {

View file

@ -10,27 +10,55 @@ import { definePluginSettings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary"; import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { SelectedGuildStore, useState } from "@webpack/common"; import { GuildStore, SelectedGuildStore, useState } from "@webpack/common";
import { User } from "discord-types/general"; import { User } from "discord-types/general";
const settings = definePluginSettings({ const settings = definePluginSettings({
showAtSymbol: { showAtSymbol: {
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
description: "Whether the the @ symbol should be displayed", description: "Whether the the @ symbol should be displayed on user mentions",
default: true default: true
} }
}); });
function DefaultRoleIcon() {
return (
<svg
className="vc-mentionAvatars-icon vc-mentionAvatars-role-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
>
<path
d="M14 8.00598C14 10.211 12.206 12.006 10 12.006C7.795 12.006 6 10.211 6 8.00598C6 5.80098 7.794 4.00598 10 4.00598C12.206 4.00598 14 5.80098 14 8.00598ZM2 19.006C2 15.473 5.29 13.006 10 13.006C14.711 13.006 18 15.473 18 19.006V20.006H2V19.006Z"
/>
<path
d="M20.0001 20.006H22.0001V19.006C22.0001 16.4433 20.2697 14.4415 17.5213 13.5352C19.0621 14.9127 20.0001 16.8059 20.0001 19.006V20.006Z"
/>
<path
d="M14.8834 11.9077C16.6657 11.5044 18.0001 9.9077 18.0001 8.00598C18.0001 5.96916 16.4693 4.28218 14.4971 4.0367C15.4322 5.09511 16.0001 6.48524 16.0001 8.00598C16.0001 9.44888 15.4889 10.7742 14.6378 11.8102C14.7203 11.8418 14.8022 11.8743 14.8834 11.9077Z"
/>
</svg>
);
}
export default definePlugin({ export default definePlugin({
name: "MentionAvatars", name: "MentionAvatars",
description: "Shows user avatars inside mentions", description: "Shows user avatars and role icons inside mentions",
authors: [Devs.Ven, Devs.Luna], authors: [Devs.Ven, Devs.SerStars],
patches: [{ patches: [{
find: ".USER_MENTION)", find: ".USER_MENTION)",
replacement: { replacement: {
match: /children:"@"\.concat\((null!=\i\?\i:\i)\)(?<=\.useName\((\i)\).+?)/, match: /children:"@"\.concat\((null!=\i\?\i:\i)\)(?<=\.useName\((\i)\).+?)/,
replace: "children:$self.renderUsername({username:$1,user:$2})" replace: "children:$self.renderUsername({username:$1,user:$2})"
} }
},
{
find: ".ROLE_MENTION)",
replacement: {
match: /children:\[\i&&.{0,50}\.RoleDot.{0,300},\i(?=\])/,
replace: "$&,$self.renderRoleIcon(arguments[0])"
}
}], }],
settings, settings,
@ -46,12 +74,31 @@ export default definePlugin({
onMouseEnter={() => setIsHovering(true)} onMouseEnter={() => setIsHovering(true)}
onMouseLeave={() => setIsHovering(false)} onMouseLeave={() => setIsHovering(false)}
> >
<img src={user.getAvatarURL(SelectedGuildStore.getGuildId(), 16, isHovering)} className="vc-mentionAvatars-avatar" /> <img
src={user.getAvatarURL(SelectedGuildStore.getGuildId(), 16, isHovering)}
className="vc-mentionAvatars-icon"
style={{ borderRadius: "50%" }}
/>
{getUsernameString(username)} {getUsernameString(username)}
</span> </span>
); );
}, { noop: true }) }, { noop: true }),
renderRoleIcon: ErrorBoundary.wrap(({ roleId, guildId }: { roleId: string, guildId: string; }) => {
// Discord uses Role Mentions for uncached users because .... idk
if (!roleId) return null;
const role = GuildStore.getRole(guildId, roleId);
if (!role?.icon) return <DefaultRoleIcon />;
return (
<img
className="vc-mentionAvatars-icon vc-mentionAvatars-role-icon"
src={`${location.protocol}//${window.GLOBAL_ENV.CDN_HOST}/role-icons/${roleId}/${role.icon}.webp?size=24&quality=lossless`}
/>
);
}),
}); });
function getUsernameString(username: string) { function getUsernameString(username: string) {

View file

@ -1,8 +1,11 @@
.vc-mentionAvatars-avatar { .vc-mentionAvatars-icon {
vertical-align: middle; vertical-align: middle;
width: 1em !important; /* insane discord sets width: 100% in channel topic */ width: 1em !important; /* insane discord sets width: 100% in channel topic */
height: 1em; height: 1em;
margin: 0 4px 0.2rem 2px; margin: 0 4px 0.2rem 2px;
border-radius: 50%;
box-sizing: border-box; box-sizing: border-box;
} }
.vc-mentionAvatars-role-icon {
margin: 0 2px 0.2rem 4px;
}

View file

@ -20,18 +20,16 @@ import "./style.css";
import { NavContextMenuPatchCallback } from "@api/ContextMenu"; import { NavContextMenuPatchCallback } from "@api/ContextMenu";
import ErrorBoundary from "@components/ErrorBoundary"; import ErrorBoundary from "@components/ErrorBoundary";
import { ExpandableHeader } from "@components/ExpandableHeader";
import { NotesIcon, OpenExternalIcon } from "@components/Icons"; import { NotesIcon, OpenExternalIcon } from "@components/Icons";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { classes } from "@utils/misc"; import { classes } from "@utils/misc";
import definePlugin from "@utils/types"; import definePlugin from "@utils/types";
import { findByPropsLazy } from "@webpack"; import { findByPropsLazy } from "@webpack";
import { Alerts, Button, Menu, Parser, TooltipContainer, useState } from "@webpack/common"; import { Alerts, Button, Menu, Parser, TooltipContainer } from "@webpack/common";
import { Guild, User } from "discord-types/general"; import { Guild, User } from "discord-types/general";
import { Auth, initAuth, updateAuth } from "./auth"; import { Auth, initAuth, updateAuth } from "./auth";
import { openReviewsModal } from "./components/ReviewModal"; import { openReviewsModal } from "./components/ReviewModal";
import ReviewsView from "./components/ReviewsView";
import { NotificationType } from "./entities"; import { NotificationType } from "./entities";
import { getCurrentUserInfo, readNotification } from "./reviewDbApi"; import { getCurrentUserInfo, readNotification } from "./reviewDbApi";
import { settings } from "./settings"; import { settings } from "./settings";
@ -78,28 +76,12 @@ export default definePlugin({
}, },
patches: [ patches: [
{
find: "showBorder:null",
replacement: {
match: /user:(\i),setNote:\i,canDM.+?\}\)/,
replace: "$&,$self.getReviewsComponent($1)"
}
},
{
find: /inline:!1,profileViewedAnalytics:\i}\),/,
replacement: {
match: /currentUser:\i,guild:\i}\)(?<=user:(\i),bio:null==\i\?.+?)/,
replace: "$&,$self.getReviewsComponent($1)"
},
predicate: () => !settings.store.preferButtonOverDropdown
},
{ {
find: ".BITE_SIZE,user:", find: ".BITE_SIZE,user:",
replacement: { replacement: {
match: /{profileType:\i\.\i\.BITE_SIZE,children:\[/, match: /{profileType:\i\.\i\.BITE_SIZE,children:\[/,
replace: "$&$self.BiteSizeReviewsButton({user:arguments[0].user})," replace: "$&$self.BiteSizeReviewsButton({user:arguments[0].user}),"
}, }
predicate: () => settings.store.preferButtonOverDropdown
}, },
{ {
find: ".FULL_SIZE,user:", find: ".FULL_SIZE,user:",
@ -171,31 +153,6 @@ export default definePlugin({
}, 4000); }, 4000);
}, },
getReviewsComponent: ErrorBoundary.wrap((user: User) => {
const [reviewCount, setReviewCount] = useState<number>();
return (
<ExpandableHeader
headerText="User Reviews"
onMoreClick={() => openReviewsModal(user.id, user.username)}
moreTooltipText={
reviewCount && reviewCount > 50
? `View all ${reviewCount} reviews`
: "Open Review Modal"
}
onDropDownClick={state => settings.store.reviewsDropdownState = !state}
defaultState={settings.store.reviewsDropdownState}
>
<ReviewsView
discordId={user.id}
name={user.username}
onFetchReviews={r => setReviewCount(r.reviewCount)}
showInput
/>
</ExpandableHeader>
);
}, { message: "Failed to render Reviews" }),
BiteSizeReviewsButton: ErrorBoundary.wrap(({ user }: { user: User; }) => { BiteSizeReviewsButton: ErrorBoundary.wrap(({ user }: { user: User; }) => {
return ( return (
<TooltipContainer text="View Reviews"> <TooltipContainer text="View Reviews">
@ -212,4 +169,4 @@ export default definePlugin({
</TooltipContainer> </TooltipContainer>
); );
}, { noop: true }) }, { noop: true })
}); });

View file

@ -54,12 +54,6 @@ export const settings = definePluginSettings({
description: "Hide reviews from blocked users", description: "Hide reviews from blocked users",
default: true, default: true,
}, },
preferButtonOverDropdown: {
description: "Show a button instead of dropdown to view reviews",
type: OptionType.BOOLEAN,
default: true,
restartNeeded: true
},
buttons: { buttons: {
type: OptionType.COMPONENT, type: OptionType.COMPONENT,
description: "ReviewDB buttons", description: "ReviewDB buttons",

View file

@ -552,6 +552,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "llytz", name: "llytz",
id: 1271128098301022240n id: 1271128098301022240n
}, },
SerStars: {
name: "SerStars",
id: 861631850681729045n,
},
} satisfies Record<string, Dev>); } satisfies Record<string, Dev>);
export const EquicordDevs = Object.freeze({ export const EquicordDevs = Object.freeze({