Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Angelix1 authored Jan 28, 2024
1 parent 4539f43 commit 008c1d9
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 0 deletions.
126 changes: 126 additions & 0 deletions plugins/cuc/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import settingPage from "./setting";
import { makeDefaults } from "./util";

import { before, after } from "@vendetta/patcher";
import { storage } from "@vendetta/plugin";
import { logger } from "@vendetta";
import { React, ReactNative, FluxDispatcher, constants } from "@vendetta/metro/common"
import { find, findByProps, findByStoreName, findByName } from "@vendetta/metro";
import { General } from "@vendetta/ui/components";
import { semanticColors } from "@vendetta/ui";

const { Text } = General;

const ThemeStore = findByStoreName("ThemeStore");
const resolveSemanticColor = find(m => m.default?.internal?.resolveSemanticColor)?.default.internal.resolveSemanticColor
?? find(m => m.meta?.resolveSemanticColor)?.meta.resolveSemanticColor ?? (() => {});

const UserStore = findByStoreName("UserStore");
const RelationshipStore = findByStoreName("RelationshipStore");
const GuildMemberStore = findByStoreName("GuildMemberStore");
const TypingWrapper = findByProps("TYPING_WRAPPER_HEIGHT");
const { DCDChatManager } = ReactNative.NativeModules;

makeDefaults(storage, {
colors: {
hex: "#DAFAF0",
},
switches: {
enableUsername: true,
enableReply: false,
enableType: false,
},
})

function resolveColor(s) {
if(s?.colors?.hex) return ReactNative.processColor(s.colors.hex)
return 0;
}

const patches = [];

export default {
onLoad: () => {
patches.push(
before("updateRows", DCDChatManager, (args) => {
let rows = JSON.parse(args[1]);

for (const row of rows) {
const { message } = row
if(!message) continue;

const handleColor = (m) => {
return m.usernameColor = resolveColor(storage)
};

if(storage?.switches?.enableUsername) {
handleColor(message)
}

if(
message?.referencedMessage?.message &&
storage?.switches?.enableReply
) {
handleColor(message?.referencedMessage?.message)
}
}
args[1] = JSON.stringify(rows);
}),

after("default", TypingWrapper, ([{ channel }], res) => {
if (!storage?.switches?.enableType) return;
if (!res) return;
const Typing = res.props?.children;
const defaultTypingColor = resolveSemanticColor(ThemeStore.theme, semanticColors.HEADER_SECONDARY);

const unpatchTyping = after("type", Typing, (_, res) => {
React.useEffect(() => () => { unpatchTyping() }, []);
const typingThing = res?.props?.children?.[0]?.props?.children?.[1]?.props;

if (
!typingThing ||
!typingThing.children ||
typingThing.children?.toLowerCase() === "several people are typing..."
) return;

const users = TypingWrapper.useTypingUserIds(channel.id).map(user => {
const member = GuildMemberStore.getMember(channel.guild_id, user);
const userobj = UserStore.getUser(user);
const name = (member?.nick || RelationshipStore.getNickname(user) || userobj.globalName || userobj.username);
const color = (storage?.colors?.hex || defaultTypingColor);

return {displayName: name, displayColor: color};
});

function userElem(user) {
return React.createElement(
Text,
{
style: {
color: user.displayColor,
fontFamily: constants.Fonts.DISPLAY_SEMIBOLD
}
},
user.displayName
);
};

if (!users || users.length < 1) return;

typingThing.children = (
users.length === 1 ?
[userElem(users[0]), " is typing..."] :
[
...users.slice(0, users.length - 1).flatMap((el, i) => [userElem(el), i < (users.length-2) ? ", " : " and "]),
userElem(users[users.length - 1]), " are typing..."
]
)
});
}),
)
},
onUnload: () => {
patches.forEach(un => un());
},
settings: settingPage
}
14 changes: 14 additions & 0 deletions plugins/cuc/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "Custom Username Color 0.1",
"description": "Override Username Colors and customize them.",
"authors": [
{
"name": "Angelica",
"id": "692632336961110087"
}
],
"main": "index.js",
"vendetta": {
"icon": "ic_legacy_username"
}
}
93 changes: 93 additions & 0 deletions plugins/cuc/setting.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import * as util from "./util";

import { ReactNative } from "@vendetta/metro/common";
import { General, Forms } from "@vendetta/ui/components";
import { getAssetIDByName } from "@vendetta/ui/assets";
import { storage } from "@vendetta/plugin";
import { useProxy } from "@vendetta/storage";
import { find, findByName, findByProps, findByStoreName } from "@vendetta/metro";
import { showToast } from "@vendetta/ui/toasts";

const { openLazy, hideActionSheet } = findByProps("openLazy", "hideActionSheet");
const { ScrollView, View, Text, TouchableOpacity, TextInput, Pressable, Image } = General;
const { FormIcon, FormSwitchRow, FormSwitch, FormRow, FormInput, FormDivider } = Forms;
const CustomColorPickerActionSheet = findByName("CustomColorPickerActionSheet");

function numToHex(numericColor) {
const red = (numericColor >> 16) & 255;
const green = (numericColor >> 8) & 255;
const blue = numericColor & 255;
return `#${((1 << 24) | (red << 16) | (green << 8) | blue).toString(16).slice(1)}`;
}

function createSwitch(id, label, sub, def, icon) {
return { id, label, sub, def, icon }
}


const switches = [
createSwitch("enableUsername", "Toggle for username", null, true, null),
createSwitch("enableReply", "Toggle for replied messages", null, false, null),
createSwitch("enableType", "Toggle for typing indicator", null, false, null)

]

export default () => {
useProxy(storage);

const pc = (inp) => ReactNative.processColor(inp);

const whenPressed = () => util?.openSheet(
CustomColorPickerActionSheet, {
color: (pc(storage?.colors?.hex) || 0),
onSelect: (color) => {
const hex = numToHex(color)
storage.colors.hex = hex
// showToast(storage.colors.hex)
}
}
);

return (
<ScrollView>
<FormRow
label="Color"
subLabel="Click to Update"
onPress={whenPressed}
trailing={
<TouchableOpacity onPress={whenPressed}>
<Image
source={{ uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mJsrQAAAgwBAJ9P6qYAAAAASUVORK5CYII=' }}
style={{
width: 96,
height: 96,
borderRadius: 10,
backgroundColor: storage?.colors?.hex || "#000"
}}
/>
</TouchableOpacity>
}
/>
{
switches?.map((obj, index) => {
return (<>
<FormRow
label={obj?.label}
subLabel={obj?.sub}
leading={obj?.icon && <FormIcon style={{ opacity: 1 }} source={getAssetIDByName(obj?.icon)} />}
trailing={
("id" in obj) ? (
<FormSwitch
value={storage?.switches[obj?.id] ?? obj?.def}
onValueChange={ (value) => (storage.switches[obj?.id] = value) }
/>
) : undefined
}
/>
{index !== switches?.length - 1 && <FormDivider />}
</>)
})
}
</ScrollView>
);
};
37 changes: 37 additions & 0 deletions plugins/cuc/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { logger } from "@vendetta";
import { find, findByName, findByProps, findByStoreName } from "@vendetta/metro";

const { openLazy, hideActionSheet } = findByProps("openLazy", "hideActionSheet");

export function makeDefaults(object, defaults) {
if (object != undefined) {
if (defaults != undefined) {
for (const key of Object.keys(defaults)) {
if (typeof defaults[key] === "object" && !Array.isArray(defaults[key])) {
if (typeof object[key] !== "object") object[key] = {};
makeDefaults(object[key], defaults[key]);
}
else {
object[key] ??= defaults[key];
}
}
}
}
}


export function openSheet(sheet, props) {
try {
openLazy(
new Promise((call) => call({ default: sheet })),
"ActionSheet",
props
);
}
catch (e) {
logger.error(e.stack);
showToast(
"Got error when opening ActionSheet! Please check debug logs"
);
}
}

0 comments on commit 008c1d9

Please sign in to comment.