feat(iRememberYou): Give UIDs and GIDs interactivity (#601)
* feat(iRememberYou): implement complete interactivity for UIDs and GIDs - add lmb copy functionality for uids with toast - add rmb context menu for uids and group headers - add invite link storage and permission aware collection for groups * fix: update username in EquicordDevs array
This commit is contained in:
parent
37da8ded0a
commit
189b488027
6 changed files with 90 additions and 12 deletions
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { DataStore } from "@api/index";
|
||||
import { Guild, User } from "@vencord/discord-types";
|
||||
import { ChannelStore, GuildMemberStore, GuildStore, MessageStore, UserStore, } from "@webpack/common";
|
||||
import { ChannelStore, GuildMemberStore, GuildStore, InviteActions, MessageStore, PermissionStore, UserStore, } from "@webpack/common";
|
||||
|
||||
export interface IUserExtra {
|
||||
isOwner?: boolean;
|
||||
|
|
@ -25,6 +25,7 @@ export interface GroupData {
|
|||
id: string;
|
||||
users: { [key: string]: IStorageUser; };
|
||||
name: string;
|
||||
inviteLink?: string;
|
||||
}
|
||||
|
||||
export class Data {
|
||||
|
|
@ -78,6 +79,8 @@ export class Data {
|
|||
array: { user: User; source?: Guild; extra?: IUserExtra; }[]
|
||||
) {
|
||||
const target = this.usersCollection;
|
||||
const processedGuilds = new Set<string>();
|
||||
|
||||
for (const { user, source, extra } of array) {
|
||||
if (user.bot) {
|
||||
continue;
|
||||
|
|
@ -87,7 +90,8 @@ export class Data {
|
|||
const group = (target[groupKey] ||= {
|
||||
name: source?.name || "dm",
|
||||
id: source?.id || user.id,
|
||||
users: {}
|
||||
users: {},
|
||||
inviteLink: undefined
|
||||
});
|
||||
const usersField = group.users;
|
||||
const previouExtra = usersField[user.id]?.extra ?? {};
|
||||
|
|
@ -100,6 +104,11 @@ export class Data {
|
|||
extra: { ...previouExtra, ...extra },
|
||||
iconURL: user.getAvatarURL(),
|
||||
};
|
||||
|
||||
if (source && !processedGuilds.has(source.id) && this.hasInvitePermissions(source.id)) {
|
||||
this.collectInviteLink(source.id);
|
||||
processedGuilds.add(source.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +147,11 @@ export class Data {
|
|||
target.add({ user, source: guild, extra: { updatedAt: now } });
|
||||
}
|
||||
|
||||
this.processUsersToCollection([...target]);
|
||||
this.processUsersToCollection([...target]);
|
||||
|
||||
if (guild && this.hasInvitePermissions(guild.id)) {
|
||||
this.collectInviteLink(guild.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,6 +176,38 @@ export class Data {
|
|||
this.processUsersToCollection([...target]);
|
||||
}
|
||||
|
||||
hasInvitePermissions(guildId: string): boolean {
|
||||
const guild = GuildStore.getGuild(guildId);
|
||||
if (!guild) return false;
|
||||
|
||||
const currentUser = UserStore.getCurrentUser();
|
||||
if (!currentUser) return false;
|
||||
|
||||
if (guild.ownerId === currentUser.id) return true;
|
||||
|
||||
const member = GuildMemberStore.getMember(guildId, currentUser.id);
|
||||
if (!member) return false;
|
||||
|
||||
return PermissionStore.can(PermissionStore.CREATE_INSTANT_INVITE, guild.id);
|
||||
}
|
||||
|
||||
async collectInviteLink(guildId: string) {
|
||||
try {
|
||||
const invites = await InviteActions.getInvites(guildId);
|
||||
if (invites && invites.length > 0) {
|
||||
const invite = invites[0];
|
||||
const inviteCode = invite.code;
|
||||
const inviteLink = `https://discord.gg/${inviteCode}`;
|
||||
|
||||
if (this.usersCollection[guildId]) {
|
||||
this.usersCollection[guildId].inviteLink = inviteLink;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("Failed to collect invite link for guild:", guildId, error);
|
||||
}
|
||||
}
|
||||
|
||||
storageAutoSaveProtocol() {
|
||||
this._storageAutoSaveProtocol_interval = setInterval(
|
||||
this.updateStorage.bind(this),
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import { HeadingPrimary } from "@components/Heading";
|
|||
import { Paragraph } from "@components/Paragraph";
|
||||
import { SettingsTab, wrapTab } from "@components/settings";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { openUserProfile } from "@utils/discord";
|
||||
import { Avatar, Clickable, React, TextInput, Tooltip, } from "@webpack/common";
|
||||
import { copyWithToast, openUserProfile } from "@utils/discord";
|
||||
import { Avatar, Clickable, ContextMenuApi, Menu, React, TextInput, Tooltip, UserStore } from "@webpack/common";
|
||||
|
||||
import { Data, IStorageUser } from "./data";
|
||||
|
||||
|
|
@ -66,10 +66,38 @@ function UserRow({ user, allowOwner = true }: { user: IStorageUser, allowOwner?:
|
|||
</Paragraph>
|
||||
}
|
||||
</Tooltip>
|
||||
<span className={cl("user-id")}>
|
||||
<Paragraph>
|
||||
{user.id}
|
||||
</Paragraph>
|
||||
<span
|
||||
className={cl("user-id")}
|
||||
onContextMenu={e => {
|
||||
e.preventDefault();
|
||||
const userObj = UserStore.getUser(user.id);
|
||||
if (userObj) {
|
||||
ContextMenuApi.openContextMenu(e, () => (
|
||||
<Menu.Menu
|
||||
navId="user-context-menu"
|
||||
onClose={ContextMenuApi.closeContextMenu}
|
||||
aria-label="User Options"
|
||||
>
|
||||
<Menu.MenuItem
|
||||
id="copy-user-id"
|
||||
label="Copy User ID"
|
||||
action={() => copyWithToast(user.id, "User ID copied to clipboard")}
|
||||
/>
|
||||
<Menu.MenuItem
|
||||
id="view-profile"
|
||||
label="View Profile"
|
||||
action={() => openUserProfile(user.id)}
|
||||
/>
|
||||
</Menu.Menu>
|
||||
));
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Clickable onClick={() => copyWithToast(user.id, "User ID copied to clipboard")}>
|
||||
<Paragraph>
|
||||
{user.id}
|
||||
</Paragraph>
|
||||
</Clickable>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import DataUI from "./components/ui";
|
|||
export default definePlugin({
|
||||
name: "IRememberYou",
|
||||
description: "Locally saves everyone you've been communicating with (including servers), in case of lose",
|
||||
authors: [EquicordDevs.zoodogood],
|
||||
authors: [EquicordDevs.zoodogood, EquicordDevs.keyages],
|
||||
dependencies: ["MessageEventsAPI"],
|
||||
|
||||
patches: [],
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@
|
|||
align-self: flex-start;
|
||||
opacity: 0.75;
|
||||
height: min-content;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vc-i-remember-you-user-id:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.vc-i-remember-you-user {
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ async function react(channelId: string, messageId: string, emoji: string) {
|
|||
export default definePlugin({
|
||||
name: "MessageClickActions",
|
||||
description: "Hold Backspace and click to delete, double click to edit/reply, triple click to react",
|
||||
authors: [Devs.Ven, EquicordDevs.keircn],
|
||||
authors: [Devs.Ven, EquicordDevs.keyages],
|
||||
|
||||
settings,
|
||||
|
||||
|
|
|
|||
|
|
@ -1221,7 +1221,7 @@ export const EquicordDevs = Object.freeze({
|
|||
name: "Benjii",
|
||||
id: 463702169443368970n
|
||||
},
|
||||
keircn: {
|
||||
keyages: {
|
||||
name: "Key",
|
||||
id: 1230319937155760131n
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue