mirror of
https://github.com/Equicord/Equicord.git
synced 2025-03-04 00:10:05 -05:00
Merge branch 'dev'
This commit is contained in:
commit
549ff6db68
8 changed files with 79 additions and 91 deletions
34
README.md
34
README.md
|
@ -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.
|
[](https://github.com/Equicord/Equibop)
|
||||||
|
[](https://github.com/Equicord/Equicord/actions/workflows/test.yml)
|
||||||
|
[](https://discord.gg/VasF3Ma4Ab)
|
||||||
|
|
||||||

|
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
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 })
|
||||||
});
|
});
|
|
@ -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",
|
||||||
|
|
|
@ -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({
|
||||||
|
|
Loading…
Add table
Reference in a new issue