Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions packages/discord-types/src/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,20 @@ export interface CommandOptions {
max_value?: number;
autocomplete?: boolean;
}

export interface OpenUserProfileModalProps {
userId: string;
guildId: string | null | undefined;
showGuildProfile?: boolean;
channelId: string;
analyticsLocation: {
page: string;
section: string;
};
section?: "USER_INFO" | "BOT_INFO" | "ACTIVITY" | "MUTUAL_GUILDS" | "MUTUAL_FRIENDS" | "BOT_DATA_ACCESS";
subsection?: "ROLES" | "CONNECTIONS" | "NOTE" | "RECENT_ACTIVITY";
}

export interface UserProfileActions {
openUserProfileModal(props: OpenUserProfileModalProps): Promise<void>;
}
15 changes: 12 additions & 3 deletions src/components/settings/tabs/plugins/components/SliderSetting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,20 @@ export function SliderSetting({ option, pluginSettings, definedSettings, id, onC

const [error, setError] = useState<string | null>(null);

function getValue(value: number): number {
if (option.onlyInts) {
return Math.round(value);
}
return value;
}

function handleChange(newValue: number): void {
const isValid = option.isValid?.call(definedSettings, newValue) ?? true;
const isValid = option.isValid?.call(definedSettings, getValue(newValue)) ?? true;

setError(resolveError(isValid));

if (isValid === true) {
onChange(newValue);
onChange(getValue(newValue));
}
}

Expand All @@ -44,7 +51,9 @@ export function SliderSetting({ option, pluginSettings, definedSettings, id, onC
maxValue={option.markers[option.markers.length - 1]}
initialValue={def}
onValueChange={handleChange}
onValueRender={(v: number) => String(v.toFixed(2))}
keyboardStep={option.onlyInts ? 1 : undefined}
onValueRender={(v: number) => String(option.onlyInts ? Math.round(v) : v.toFixed(2))}
onMarkerRender={(v: number) => option.markers.includes(v) ? String(getValue(v)) : null}
stickToMarkers={option.stickToMarkers ?? true}
disabled={option.disabled?.call(definedSettings) ?? false}
{...option.componentProps}
Expand Down
53 changes: 47 additions & 6 deletions src/plugins/showConnections/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ import ErrorBoundary from "@components/ErrorBoundary";
import { Flex } from "@components/Flex";
import { CopyIcon, LinkIcon } from "@components/Icons";
import { Devs } from "@utils/constants";
import { openUserProfile } from "@utils/discord";
import { copyWithToast } from "@utils/misc";
import definePlugin, { OptionType } from "@utils/types";
import definePlugin, { makeRange, OptionType } from "@utils/types";
import { ConnectedAccount, User } from "@vencord/discord-types";
import { findByCodeLazy, findByPropsLazy } from "@webpack";
import { Tooltip, UserProfileStore } from "@webpack/common";
import { Clickable, Tooltip, UserProfileStore } from "@webpack/common";
import OpenInAppPlugin from "plugins/openInApp";

import { VerifiedIcon } from "./VerifiedIcon";
Expand Down Expand Up @@ -58,6 +59,14 @@ const settings = definePluginSettings({
{ label: "Cozy", value: Spacing.COZY }, // US Spelling :/
{ label: "Roomy", value: Spacing.ROOMY }
]
},
maxNumberOfConnections: {
type: OptionType.SLIDER,
description: "Max number of connections to show",
markers: makeRange(6, 48, 7),
default: 13,
stickToMarkers: false,
onlyInts: true,
}
});

Expand All @@ -82,20 +91,52 @@ function ConnectionsComponent({ id, theme }: { id: string, theme: string; }) {
if (!profile)
return null;

const connections = profile.connectedAccounts;
if (!connections?.length)
const { connectedAccounts } = profile;
if (!connectedAccounts?.length)
return null;

const connections = connectedAccounts.map(connection => <CompactConnectionComponent connection={connection} theme={theme} key={connection.id} />);

if (connectedAccounts.length > settings.store.maxNumberOfConnections) {
connections.length = settings.store.maxNumberOfConnections;
connections.push(<ConnectionsMoreIcon
key="more-connections"
onClick={() => openUserProfile(id, {
section: "USER_INFO",
subsection: "CONNECTIONS"
})}
/>);
}

return (
<Flex style={{
gap: getSpacingPx(settings.store.iconSpacing),
flexWrap: "wrap"
}}>
{connections.map(connection => <CompactConnectionComponent connection={connection} theme={theme} key={connection.id} />)}
{connections}
</Flex>
);
}


function ConnectionsMoreIcon({ onClick }: { onClick: () => void; }) {
return (
<Tooltip text="View all Connections">
{props => (
<Clickable
{...props}
onClick={onClick}
>
{/* discords icon refuses to work with a custom width/height for some reason, so we use our own SVG */}
<svg width={settings.store.iconSize} height={settings.store.iconSize} viewBox="0 0 24 24">
<path fill="var(--interactive-normal)" fillRule="evenodd" d="M4 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4Zm10-2a2 2 0 1 1-4 0 2 2 0 0 1 4 0Zm8 0a2 2 0 1 1-4 0 2 2 0 0 1 4 0Z" clipRule="evenodd"></path>
</svg>
</Clickable>
)}
</Tooltip>
);
}

function CompactConnectionComponent({ connection, theme }: { connection: ConnectedAccount, theme: string; }) {
const platform = platforms.get(useLegacyPlatformType(connection.type));
const url = platform.getPlatformUserUrl?.(connection);
Expand Down Expand Up @@ -157,7 +198,7 @@ function CompactConnectionComponent({ connection, theme }: { connection: Connect
export default definePlugin({
name: "ShowConnections",
description: "Show connected accounts in user popouts",
authors: [Devs.TheKodeToad],
authors: [Devs.TheKodeToad, Devs.sadan],
settings,

patches: [
Expand Down
7 changes: 4 additions & 3 deletions src/utils/discord.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/

import { MessageObject } from "@api/MessageEvents";
import { Channel, CloudUpload, Guild, GuildFeatures, Message, User } from "@vencord/discord-types";
import { Channel, CloudUpload, Guild, GuildFeatures, Message, OpenUserProfileModalProps, User } from "@vencord/discord-types";
import { ChannelActionCreators, ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, IconUtils, InviteActions, MessageActions, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common";
import { Except } from "type-fest";

Expand Down Expand Up @@ -164,7 +164,7 @@ export function openImageModal(item: Except<MediaModalItem, "type">, mediaModalP
});
}

export async function openUserProfile(id: string) {
export async function openUserProfile(id: string, extraOptions: Partial<OpenUserProfileModalProps> = {}) {
const user = await UserUtils.getUser(id);
if (!user) throw new Error("No such user: " + id);

Expand All @@ -176,7 +176,8 @@ export async function openUserProfile(id: string) {
analyticsLocation: {
page: guildId ? "Guild Channel" : "DM Channel",
section: "Profile Popout"
}
},
...extraOptions,
});
}

Expand Down
6 changes: 6 additions & 0 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,12 @@ export interface PluginSettingSliderDef {
* If false, allow users to select values in-between your markers.
*/
stickToMarkers?: boolean;
/**
* If true, only allow integers to be selected.
*
* If {@link stickToMarkers} is enabled this will have no effect
*/
onlyInts?: boolean;
}

export interface IPluginOptionComponentProps {
Expand Down
2 changes: 1 addition & 1 deletion src/webpack/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export const { zustandPersist } = mapMangledModuleLazy(".onRehydrateStorage)?",

export const MessageActions = findByPropsLazy("editMessage", "sendMessage");
export const MessageCache = findByPropsLazy("clearCache", "_channelMessages");
export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal");
export const UserProfileActions: t.UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal");
export const InviteActions = findByPropsLazy("resolveInvite");
export const ChannelActionCreators = findByPropsLazy("openPrivateChannel");

Expand Down