Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stricter TypeScript usage #76

Merged
merged 4 commits into from
Dec 23, 2024
Merged
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
6 changes: 3 additions & 3 deletions ActivityIcons/src/components/ActivityIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Components } from "betterdiscord";
import { Icons } from "../modules/discordmodules";
import { Settings, Strings, isBot } from "../modules/utils";
import { Component as Playstation } from "../assets/playstation.svg";
import { Component as Xbox } from "../assets/xbox.svg";
import { parseStringReact } from "@lib/utils/string";
import { Activity, RichActivity } from "@discord/icons";

interface ActivityIconProps {
activities: any[];
Expand Down Expand Up @@ -55,10 +55,10 @@ export default function ActivityIcon(props: ActivityIconProps) {
});
}

let icon = <Icons.Activity color="currentColor" size="13" width="13" height="13" />;
let icon = <Activity color="currentColor" size="13" width="13" height="13" />;
if (platformIcons && onPS) icon = <Playstation color="currentColor" size="13" width="13" height="13" />;
if (platformIcons && onXbox) icon = <Xbox color="currentColor" size="13" width="13" height="13" />;
if (richPresenceIcons && hasRP) icon = <Icons.RichActivity color="currentColor" size="16" width="16" height="16" />;
if (richPresenceIcons && hasRP) icon = <RichActivity color="currentColor" size="16" width="16" height="16" />;

return tooltip ? (
<Components.Tooltip text={tooltip} position="top">
Expand Down
6 changes: 3 additions & 3 deletions ActivityIcons/src/components/ListeningIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Components } from "betterdiscord";
import { Icons } from "../modules/discordmodules";
import { isBot, Settings, Strings } from "../modules/utils";
import { parseString } from "@lib/utils/string";
import { Headset } from "@discord/icons";

interface ListeningIconProps {
activities: any[];
Expand Down Expand Up @@ -32,9 +32,9 @@ export default function ListeningIcon(props: ListeningIconProps) {
}
position="top"
>
{(props) => (
{(props: any) => (
<div {...props} className="activity-icon">
<Icons.Headset color="currentColor" size="13" width="13" height="13" />
<Headset color="currentColor" size="13" width="13" height="13" />
</div>
)}
</Components.Tooltip>
Expand Down
2 changes: 1 addition & 1 deletion ActivityIcons/src/components/SettingsPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Common } from "../modules/discordmodules";
import { Common } from "@discord/components";
import { Settings, Strings } from "../modules/utils";

export default function SettingsPanel() {
Expand Down
6 changes: 3 additions & 3 deletions ActivityIcons/src/components/WatchingIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Components } from "betterdiscord";
import { Icons } from "../modules/discordmodules";
import { isBot, Settings } from "../modules/utils";
import { Screen } from "@discord/icons";

interface WatchingIconProps {
activities: any[];
Expand All @@ -17,9 +17,9 @@ export default function WatchingIcon(props: WatchingIconProps) {

return (
<Components.Tooltip text={<strong>{activity.name}</strong>}>
{(props) => (
{(props: any) => (
<div {...props} className="activity-icon">
<Icons.Screen color="currentColor" size="13" width="13" height="13" />
<Screen color="currentColor" size="13" width="13" height="13" />
</div>
)}
</Components.Tooltip>
Expand Down
26 changes: 15 additions & 11 deletions ActivityIcons/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DOM, Patcher, Meta } from "betterdiscord";
import { DOM, Patcher, Meta, Plugin, Changes } from "betterdiscord";
import { showChangelog } from "@lib";
import {
ActivityStatus,
Expand All @@ -14,25 +14,27 @@ import ListeningIcon from "./components/ListeningIcon";
import SettingsPanel from "./components/SettingsPanel";
import WatchingIcon from "./components/WatchingIcon";

export default class ActivityIcons {
export default class ActivityIcons implements Plugin {
meta: Meta;

constructor(meta: Meta) {
this.meta = meta;
}

start() {
showChangelog(changelog, this.meta);
showChangelog(changelog as Changes[], this.meta);
DOM.addStyle(styles);
Strings.subscribe();
this.patchActivityStatus();
}

patchActivityStatus() {
Patcher.after(ActivityStatus, "ZP", (_, [props]: [any], ret) => {
if (!ActivityStatus) return;
const [module, key] = ActivityStatus;
Patcher.after(module, key, (_, [props], ret) => {
if (!ret) return;

const defaultIconIndex = ret.props.children.findIndex((element) =>
const defaultIconIndex = ret.props.children.findIndex((element: any) =>
element?.props?.className?.startsWith("icon")
);

Expand All @@ -46,18 +48,20 @@ export default class ActivityIcons {
<ListeningIcon activities={props.activities} />
);
});
forceUpdateAll(memberSelector, (i) => i.user);
forceUpdateAll(peopleListItemSelector, (i) => i.user);
forceUpdateAll(privateChannelSelector);
this.forceUpdateComponents();
}

forceUpdateComponents() {
if (memberSelector) forceUpdateAll(memberSelector, (i) => i.user);
if (peopleListItemSelector) forceUpdateAll(peopleListItemSelector, (i) => i.user);
if (privateChannelSelector) forceUpdateAll(privateChannelSelector);
}

stop() {
Patcher.unpatchAll();
DOM.removeStyle();
Strings.unsubscribe();
forceUpdateAll(memberSelector, (i) => i.user);
forceUpdateAll(peopleListItemSelector, (i) => i.user);
forceUpdateAll(privateChannelSelector);
this.forceUpdateComponents();
}

getSettingsPanel() {
Expand Down
45 changes: 8 additions & 37 deletions ActivityIcons/src/modules/discordmodules.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,16 @@
import { Webpack } from "betterdiscord";
import { expectModule, expectClasses, expectSelectors, expectIcon } from "@lib/utils/webpack";
import { expectClasses, expectSelectors, expectWithKey } from "@lib/utils/webpack";
import { AnyComponent } from "@lib/utils/react";

const {
Filters: { byKeys, byStrings },
} = Webpack;

const Error = (_props) => (
<div>
<h1 style={{ color: "red" }}>Error: Component not found</h1>
</div>
);

export const ActivityStatus: any = expectModule({
filter: byStrings("QuestsIcon", "hangStatusActivity"),
export const ActivityStatus = expectWithKey<AnyComponent>({
filter: Webpack.Filters.byStrings("QuestsIcon", "hangStatusActivity"),
name: "ActivityStatus",
defaultExport: false,
fatal: true,
});

export const Icons = {
Activity: expectIcon(
"Activity",
"M20.97 4.06c0 .18.08.35.24.43.55.28.9.82 1.04 1.42.3 1.24.75 3.7.75 7.09v4.91a3.09"
),
RichActivity: expectIcon("RichActivity", "M6,7 L2,7 L2,6 L6,6 L6,7 Z M8,5 L2,5 L2,4 L8,4"),
Headset: expectIcon("Headset", "M12 3a9 9 0 0 0-8.95 10h1.87a5 5 0 0 1 4.1 2.13l1.37 1.97a3.1 3.1 0 0"),
Screen: expectIcon("Screen", "M5 2a3 3 0 0 0-3 3v8a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3V5a3 3 0 0 0-3-3H5ZM13.5 20a.5.5"),
};

export const Common = expectModule({
filter: byKeys("FormSwitch"),
name: "Common",
fallback: {
FormSwitch: Error,
},
});

export const Margins = expectClasses("Margins", ["marginBottom8"]);
export const marginClasses = expectClasses("Margins", ["marginBottom8"]);

export const peopleListItemSelector = expectSelectors("People List Classes", ["peopleListItem"]).peopleListItem;
export const peopleListItemSelector = expectSelectors("People List Classes", ["peopleListItem"])?.peopleListItem;

export const memberSelector = expectSelectors("Member Class", ["memberInner", "member"]).member;
export const memberSelector = expectSelectors("Member Class", ["memberInner", "member"])?.member;

export const privateChannelSelector = expectSelectors("Private Channel Classes", ["favoriteIcon", "channel"]).channel;
export const privateChannelSelector = expectSelectors("Private Channel Classes", ["favoriteIcon", "channel"])?.channel;
2 changes: 1 addition & 1 deletion ActivityIcons/src/modules/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const Settings = new SettingsManager({

export const Strings = new StringsManager(locales, "en-US");

export function forceUpdateAll(selector: string, propsFilter = (_) => true) {
export function forceUpdateAll(selector: string, propsFilter = (_: any) => true) {
const elements: NodeListOf<HTMLElement> = document.querySelectorAll(selector);
for (const element of elements) {
const instance = ReactUtils.getInternalInstance(element);
Expand Down
8 changes: 5 additions & 3 deletions ActivityToggle/src/components/ActivityToggleButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ContextMenu, UI } from "betterdiscord";
import { Activity, PanelButton, Sections, Settings, UserSettingsWindow, playSound, ShowCurrentGame } from "../modules";
import { PanelButton, playSound, ShowCurrentGame } from "../modules";
import ActivityDisabledIcon from "./ActivityDisabledIcon";
import { Activity, Settings } from "@discord/icons";
import { SettingsSections, UserSettingsWindow } from "@discord/modules";

export default function ActivityToggleButton() {
const activityEnabled = ShowCurrentGame.useSetting();
Expand All @@ -14,7 +16,7 @@ export default function ActivityToggleButton() {
return UI.alert("Error", "Could not update setting. See the console for more information.");
}
ShowCurrentGame.updateSetting(!activityEnabled);
playSound(activityEnabled ? "activity_user_left" : "activity_user_join", 0.4);
playSound?.(activityEnabled ? "activity_user_left" : "activity_user_join", 0.4);
}}
onContextMenu={(e: React.MouseEvent) => {
ContextMenu.open(
Expand All @@ -30,7 +32,7 @@ export default function ActivityToggleButton() {
"Could not open settings window. See the console for more information."
);
}
UserSettingsWindow.setSection(Sections.ACTIVITY_PRIVACY);
UserSettingsWindow.setSection(SettingsSections.ACTIVITY_PRIVACY);
UserSettingsWindow.open();
},
},
Expand Down
21 changes: 13 additions & 8 deletions ActivityToggle/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { DOM, Meta, Patcher, ReactUtils, Utils } from "betterdiscord";
import { DOM, Meta, Patcher, Plugin, ReactUtils, Utils } from "betterdiscord";
import { AccountSelectors } from "./modules";
import ActivityToggleButton from "./components/ActivityToggleButton";
import { Updater } from "@lib/updater";

export default class ActivityToggle {
export default class ActivityToggle implements Plugin {
forceUpdate?: () => void;
meta: Meta;

Expand All @@ -13,26 +13,31 @@ export default class ActivityToggle {

start() {
Updater.checkForUpdates(this.meta);
DOM.addStyle(`${AccountSelectors.avatarWrapper} { min-width: 70px; }`);
if (AccountSelectors) DOM.addStyle(`${AccountSelectors.avatarWrapper} { min-width: 70px; }`);
this.patch();
}

patch() {
const owner: any = ReactUtils.getOwnerInstance(document.querySelector(AccountSelectors.container));
if (!AccountSelectors) return;
const element = document.querySelector(AccountSelectors.container);
if (!element) return;
const owner: any = ReactUtils.getOwnerInstance(element as HTMLElement);
if (!owner) return;
const Account = owner._reactInternals.type;
this.forceUpdate = owner.forceUpdate.bind(owner);

Patcher.after(Account.prototype, "render", (_that, [_props], ret) => {
const buttonContainerFilter = (i) =>
Array.isArray(i?.props?.children) && i.props.children.some((e) => e?.props?.hasOwnProperty("selfMute"));
Patcher.after(Account.prototype, "render", (_that, _args, ret) => {
const buttonContainerFilter = (i: any) =>
Array.isArray(i?.props?.children) &&
i.props.children.some((e: any) => e?.props?.hasOwnProperty("selfMute"));

const buttonContainer = Utils.findInTree(ret.props.children, buttonContainerFilter, {
walkable: ["children", "props"],
});
buttonContainer.props.children.unshift(<ActivityToggleButton />);
});

this.forceUpdate();
this.forceUpdate?.();
}

stop() {
Expand Down
43 changes: 11 additions & 32 deletions ActivityToggle/src/modules.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
import { Webpack } from "betterdiscord";
import { expectModule, expectSelectors, expectIcon } from "@lib/utils/webpack";
import { byType, expectModule, expectSelectors } from "@lib/utils/webpack";
import React from "react";
import { EmptyComponent } from "@lib/utils/react";

const {
Filters: { byKeys, byStrings },
} = Webpack;

export const Sections = expectModule({
filter: byKeys("ACCOUNT", "ACCESSIBILITY"),
searchExports: true,
name: "Sections",
fallback: {
ACTIVITY_PRIVACY: "Activity Privacy",
},
});

export const PanelButton: React.FunctionComponent<any> = expectModule({
filter: byStrings("PANEL_BUTTON"),
export const PanelButton = expectModule({
filter: Webpack.Filters.byStrings("PANEL_BUTTON"),
name: "PanelButton",
fatal: true,
fallback: EmptyComponent,
});

export const Activity = expectIcon(
"Activity",
"M20.97 4.06c0 .18.08.35.24.43.55.28.9.82 1.04 1.42.3 1.24.75 3.7.75 7.09v4.91a3.09"
);

export const Settings = expectIcon("Settings", "M10.56 1.1c-.46.05-.7.53-.64.98.18 1.16-.19 2.2-.98 2.53");

export const playSound: (id: string, vol: number) => void = expectModule({
filter: byStrings("Unable to find sound for pack name:"),
export const playSound = expectModule<(sound: string, volume: number) => void>({
filter: Webpack.Filters.combine(
Webpack.Filters.byStrings("Unable to find sound for pack name:"),
byType("function")
),
name: "playSound",
searchExports: true,
});
Expand All @@ -40,16 +24,11 @@ export const ShowCurrentGame = expectModule({
fallback: {
G6: {
useSetting: () => React.useState(true),
updateSetting: undefined as (...args: any) => void,
updateSetting: undefined as ((...args: any) => void) | undefined,
},
},
})?.G6;

export const UserSettingsWindow: any = expectModule({
filter: byKeys("open", "updateAccount"),
name: "UserSettingsWindow",
});

export const AccountSelectors = expectSelectors("Account Classes", [
"avatarWrapper",
"accountProfilePopoutWrapper",
Expand Down
Loading
Loading