Skip to content

Commit

Permalink
patchSettings: Fix settings crash and patching (Aliucord#26)
Browse files Browse the repository at this point in the history
Signed-off-by: nikosszzz <[email protected]>
  • Loading branch information
nikosszzz authored Sep 18, 2022
1 parent d5bb8d0 commit 8817b0f
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 46 deletions.
2 changes: 2 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src/api/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { SnowflakeUtils } from "../metro";
export interface CommandSection {
id: string;
name: string;
type: number;
icon?: string;
}

Expand Down Expand Up @@ -81,7 +82,9 @@ export class Commands {

public static _aliucordSection: CommandSection = {
id: Commands.generateId(),
name: "Aliucord"
type: 1,
name: "Aliucord",
icon: "https://github.com/aliucord.png"
};

public static _commands: AliucordCommand[] = [];
Expand Down
31 changes: 8 additions & 23 deletions src/core-plugins/CommandHandler.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,23 @@
import { ApplicationCommand, ApplicationCommandType, Commands, CommandSection } from "../api/Commands";
import { ApplicationCommand, ApplicationCommandType, Commands } from "../api/Commands";
import { Plugin } from "../entities/Plugin";
import { getByProps } from "../metro";
import { after } from "../utils/patcher";

export default class CommandHandler extends Plugin {
start() {
const commands = getByProps("getBuiltInCommands");
commands.BUILT_IN_SECTIONS["aliucord"] = Commands._aliucordSection;
after<any, ApplicationCommand[], any>(commands, "getBuiltInCommands", context => {
if (context.args[0] != ApplicationCommandType.CHAT) return;
context.result = [...context.result, ...Commands._commands];
});

const discovery = getByProps("useApplicationCommandsDiscoveryState");
after(discovery, "useApplicationCommandsDiscoveryState", context => {
const res = context.result as any;
if (!res.discoverySections.find((s: any) => s.key === Commands._aliucordSection.id) && Commands._commands.length) {
res.discoveryCommands.push(...Commands._commands);
res.commands.push(...Commands._commands.filter(
command => !res.commands.some((cmd: ApplicationCommand) => cmd.name === command.name))
);

res.discoverySections.push({
data: Commands._commands,
key: Commands._aliucordSection.id,
section: Commands._aliucordSection
});

const offsets = res.sectionsOffset;
offsets.push(offsets[offsets.length - 1] + commands.BUILT_IN_COMMANDS.length - 1);
}

if (!res.applicationCommandSections.find((s: CommandSection) => s.id === Commands._aliucordSection.id) && Commands._commands.length) {
res.applicationCommandSections.push(Commands._aliucordSection);
}
const assets = getByProps("getApplicationIconURL");
after(assets, "getApplicationIconURL", context => {
const [props] = context.args;
if (props.id === Commands._aliucordSection.id)
context.result = Commands._aliucordSection.icon;
});

}
}
1 change: 1 addition & 0 deletions src/metro/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ export const FluxDispatcher = getByProps("isDispatching");
export const FetchUserActions = getByProps("fetchProfile");
export const ContextMenuActions = getByProps("openContextMenu");
export const SnowflakeUtils = getByProps("fromTimestamp", "extractTimestamp");
export const Locale = getByProps("Messages");

export const Clipboard = getByProps("getString", "setString") as {
getString(): Promise<string>,
Expand Down
17 changes: 17 additions & 0 deletions src/ui/ThemesPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Forms, React } from "../metro";
import { getAssetId } from "../utils/getAssetId";

const { FormSection, FormRow } = Forms;

export default function ThemesPage() {
return (
<>
<FormSection title="Themes" android_noDivider={true}>
<FormRow
leading={<FormRow.Icon source={getAssetId("ic_warning_24px")} />}
label="Coming soon"
/>
</FormSection>
</>
);
}
15 changes: 14 additions & 1 deletion src/ui/UpdaterPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
import { Forms, React } from "../metro";
import { getAssetId } from "../utils/getAssetId";

const { FormSection, FormRow } = Forms;

export default function UpdaterPage() {
return null;
return (
<>
<FormSection title="Updater" android_noDivider={true}>
<FormRow
leading={<FormRow.Icon source={getAssetId("ic_share_ios")} />}
label="Coming soon"
/>
</FormSection>
</>
);
}
43 changes: 24 additions & 19 deletions src/ui/patchSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { sha } from "aliucord-version";
import { Forms, getByName, i18n, React, ReactNative as RN } from "../metro";
import { Forms, getByName, Locale, React } from "../metro";
import { findInReactTree } from "../utils/findInReactTree";
import { after } from "../utils/patcher";
import { getAssetId } from "../utils/getAssetId";
import AliucordPage from "./AliucordPage";
import PluginsPage from "./PluginsPage";
import UpdaterPage from "./UpdaterPage";

import ThemesPage from "./ThemesPage";

export default function patchSettings() {
const { FormSection, FormRow } = Forms;
const UserSettingsOverviewWrapper = getByName("UserSettingsOverviewWrapper");

const UserSettingsOverviewWrapper = getByName("UserSettingsOverviewWrapper", { default: false });
after(getByName("getScreens"), "default", (_, res) => {
res.ASettings = {
title: "Aliucord",
Expand All @@ -21,7 +22,7 @@ export default function patchSettings() {
};
res.AThemes = {
title: "Themes",
render: () => <RN.Text>Hello World</RN.Text>
render: ThemesPage
};
res.AUpdater = {
title: "Updater",
Expand All @@ -33,55 +34,59 @@ export default function patchSettings() {
});

const unpatch = after(UserSettingsOverviewWrapper, "default", (_, res) => {
unpatch();

const { navigation } = res.props;
const Overview = findInReactTree(res, m => m.type?.name === "UserSettingsOverview");

// Yeet the funny Upload Logs button
after(res.type.prototype, "renderSupportAndAcknowledgements", (_, { props }) => {
after(Overview.type.prototype, "renderSupportAndAcknowledgements", (_, { props }) => {
const idx = props.children.findIndex(c => c?.type?.name === "UploadLogsButton");
if (idx !== -1) {
props.children.splice(idx, 1);
}
});

after(res.type.prototype, "render", (_, { props }) => {
const nitroIndex = props.children.findIndex(c => c?.props?.title === i18n.Messages.PREMIUM_SETTINGS);
after(Overview.type.prototype, "render", (_, { props }) => {
const { children } = props;

const aliucordSection = (
const searchable = [Locale.Messages["BILLING_SETTINGS"], Locale.Messages["PREMIUM_SETTINGS"]];
const index = children.findIndex(x => searchable.includes(x.props.title));

children.splice(index === -1 ? 4 : index, 0, <>
<FormSection key="AliucordSection" title={`Aliucord (${sha})`} >
<FormRow
leading={<FormRow.Icon source={getAssetId("Discord")} />}
label="Aliucord"
trailing={FormRow.Arrow}
onPress={() =>
navigation.push("ASettings")
Overview.props.navigation.push("ASettings")
}
/>
<FormRow
leading={<FormRow.Icon source={getAssetId("ic_settings")} />}
label="Plugins"
trailing={FormRow.Arrow}
onPress={() =>
navigation.push("APlugins")
Overview.props.navigation.push("APlugins")
}
/>
<FormRow
leading={<FormRow.Icon source={getAssetId("ic_theme_24px")} />}
label="Themes"
trailing={FormRow.Arrow}
onPress={() =>
navigation.push("AThemes")
Overview.props.navigation.push("AThemes")
}
/>
<FormRow
leading={<FormRow.Icon source={getAssetId("ic_share_ios")} />}
label="Updater"
trailing={FormRow.Arrow}
onPress={() =>
navigation.push("AUpdater")
Overview.props.navigation.push("AUpdater")
}
/>
</FormSection>
);

props.children.splice(nitroIndex, 0, aliucordSection);
</>);
});
unpatch();
});
}
2 changes: 1 addition & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export * as constants from "./constants";
export * from "./debug";
// export * from "./findInReactTree"; just exporting this makes the app crash with ReferenceError: Property 'ref' doesn't exist, bruh?
export * from "./findInReactTree";
export * from "./getAssetId";
export * from "./Logger";
export * from "./misc";
Expand Down
2 changes: 1 addition & 1 deletion src/utils/patcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class PatchInfo<T, R, A extends any[]> {
const lastError = ctx.error;

try {
const result = patches[idx].after(ctx as AfterPatchContext<T, R, A>, ctx.result!, ...ctx.args);
const result = patches[idx].after(ctx as AfterPatchContext<T, R, A>, ctx.result as R, ...ctx.args);
if (result !== undefined) ctx.result = result;
} catch (err: any) {
this.error(patches[idx], "PostPatch", err);
Expand Down

0 comments on commit 8817b0f

Please sign in to comment.