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
|
||||
|
||||
- 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.
|
||||
You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, changes, chat or even support.<br><br></br>
|
||||
|
||||
### Extra included plugins
|
||||
<details>
|
||||
<summary>Extra included plugins (123 additional plugins)</summary>
|
||||
|
||||
|
@ -200,17 +189,10 @@ Inject Equicord into your client:
|
|||
```shell
|
||||
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
|
||||
|
||||
Thank you to [Vendicated](https://github.com/Vendicated) for creating [Vencord](https://github.com/Vendicated/Vencord).
|
||||
|
||||
Thank you to [Suncord [EOL]](https://github.com/verticalsync/Suncord) by [VerticalSync](https://github.com/verticalsync) for helping me when needed.
|
||||
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.
|
||||
|
||||
## 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);
|
||||
showNotification({
|
||||
title: `${applicationName} - Quests Completer`,
|
||||
body: `Current progress: ${progress}/${secondsNeeded} minutes.`,
|
||||
body: `Current progress: ${progress}/${secondsNeeded} seconds.`,
|
||||
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);
|
||||
showNotification({
|
||||
title: `${applicationName} - Quests Completer`,
|
||||
body: `Current progress: ${progress}/${secondsNeeded} minutes.`,
|
||||
body: `Current progress: ${progress}/${secondsNeeded} seconds.`,
|
||||
icon: icon,
|
||||
});
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import "./styles.css";
|
|||
|
||||
import { NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import * as DataStore from "@api/DataStore";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { definePluginSettings, migratePluginSettings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
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 { SetTimezoneModal } from "./TimezoneModal";
|
||||
import { migrateData } from "plugins/pinDms/data";
|
||||
|
||||
export const DATASTORE_KEY = "vencord-timezones";
|
||||
|
||||
|
@ -137,9 +138,9 @@ const userContextMenuPatch: NavContextMenuPatchCallback = (children, { user }: {
|
|||
|
||||
};
|
||||
|
||||
|
||||
migratePluginSettings("Timezones", "Timezone");
|
||||
export default definePlugin({
|
||||
name: "Timezone",
|
||||
name: "Timezones",
|
||||
authors: [Devs.Aria],
|
||||
description: "Shows the local time of users in profiles and message headers",
|
||||
contextMenus: {
|
||||
|
|
|
@ -10,27 +10,55 @@ import { definePluginSettings } from "@api/Settings";
|
|||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
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";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
showAtSymbol: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Whether the the @ symbol should be displayed",
|
||||
description: "Whether the the @ symbol should be displayed on user mentions",
|
||||
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({
|
||||
name: "MentionAvatars",
|
||||
description: "Shows user avatars inside mentions",
|
||||
authors: [Devs.Ven, Devs.Luna],
|
||||
description: "Shows user avatars and role icons inside mentions",
|
||||
authors: [Devs.Ven, Devs.SerStars],
|
||||
patches: [{
|
||||
find: ".USER_MENTION)",
|
||||
replacement: {
|
||||
match: /children:"@"\.concat\((null!=\i\?\i:\i)\)(?<=\.useName\((\i)\).+?)/,
|
||||
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,
|
||||
|
@ -46,12 +74,31 @@ export default definePlugin({
|
|||
onMouseEnter={() => setIsHovering(true)}
|
||||
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)}
|
||||
</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) {
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
.vc-mentionAvatars-avatar {
|
||||
.vc-mentionAvatars-icon {
|
||||
vertical-align: middle;
|
||||
width: 1em !important; /* insane discord sets width: 100% in channel topic */
|
||||
height: 1em;
|
||||
margin: 0 4px 0.2rem 2px;
|
||||
border-radius: 50%;
|
||||
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 ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { ExpandableHeader } from "@components/ExpandableHeader";
|
||||
import { NotesIcon, OpenExternalIcon } from "@components/Icons";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { classes } from "@utils/misc";
|
||||
import definePlugin from "@utils/types";
|
||||
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 { Auth, initAuth, updateAuth } from "./auth";
|
||||
import { openReviewsModal } from "./components/ReviewModal";
|
||||
import ReviewsView from "./components/ReviewsView";
|
||||
import { NotificationType } from "./entities";
|
||||
import { getCurrentUserInfo, readNotification } from "./reviewDbApi";
|
||||
import { settings } from "./settings";
|
||||
|
@ -78,28 +76,12 @@ export default definePlugin({
|
|||
},
|
||||
|
||||
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:",
|
||||
replacement: {
|
||||
match: /{profileType:\i\.\i\.BITE_SIZE,children:\[/,
|
||||
replace: "$&$self.BiteSizeReviewsButton({user:arguments[0].user}),"
|
||||
},
|
||||
predicate: () => settings.store.preferButtonOverDropdown
|
||||
}
|
||||
},
|
||||
{
|
||||
find: ".FULL_SIZE,user:",
|
||||
|
@ -171,31 +153,6 @@ export default definePlugin({
|
|||
}, 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; }) => {
|
||||
return (
|
||||
<TooltipContainer text="View Reviews">
|
||||
|
|
|
@ -54,12 +54,6 @@ export const settings = definePluginSettings({
|
|||
description: "Hide reviews from blocked users",
|
||||
default: true,
|
||||
},
|
||||
preferButtonOverDropdown: {
|
||||
description: "Show a button instead of dropdown to view reviews",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
buttons: {
|
||||
type: OptionType.COMPONENT,
|
||||
description: "ReviewDB buttons",
|
||||
|
|
|
@ -552,6 +552,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
|||
name: "llytz",
|
||||
id: 1271128098301022240n
|
||||
},
|
||||
SerStars: {
|
||||
name: "SerStars",
|
||||
id: 861631850681729045n,
|
||||
},
|
||||
} satisfies Record<string, Dev>);
|
||||
|
||||
export const EquicordDevs = Object.freeze({
|
||||
|
|
Loading…
Add table
Reference in a new issue