Skip to content

Commit

Permalink
feat: badge support
Browse files Browse the repository at this point in the history
  • Loading branch information
byeoon committed Oct 18, 2024
1 parent fe523a4 commit 25da11c
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import initSettings from "@ui/settings";
import initFixes from "@lib/fixes";
import logger from "@lib/logger";
import windowObject from "@lib/windowObject";
import { initSecurity } from "./lib/security";
import { initAntiTrack } from "./tweaks/NoTracking";
import { initBadges } from "./lib/badge";


export default async () => {
Expand All @@ -25,6 +24,7 @@ export default async () => {
initSafeMode(),
initSettings(),
initQuickInstall(),
initBadges(),
]);

// Assign window object
Expand Down
36 changes: 36 additions & 0 deletions src/lib/badge/badgeComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const { View, Image, TouchableOpacity } = RN;
export const BadgeComponent = ({ name, image, size, margin, custom }: BadgeComponents) => {

const styles = stylesheet.createThemedStyleSheet({
container: {
flexDirection: "row",
alignItems: "center",
flexWrap: "wrap",
justifyContent: "flex-end",
},
img: {
width: size,
height: size,
resizeMode: "contain",
marginHorizontal: margin
}
});

const renderBadge = () => {
if (custom) {
return (custom)
} else {
return (
<TouchableOpacity onPress={() => toasts.open({ content: name, source: { uri: image } })}>
<Image style={styles.img} source={{ uri: image }} />
</TouchableOpacity>
)
}
}

return (
<View style={styles.container}>
{renderBadge()}
</View>
)
}
131 changes: 131 additions & 0 deletions src/lib/badge/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Thank you so fucking much
// https://github.com/WolfPlugs/vendetta-plugins/tree/master/plugins/globalBadges

import { findByName } from "@metro/filters";
import { after } from "@lib/patcher";
import { ReactNative as RN, React } from "@metro/common";

import { BadgeProps, CustomBadges, BadgeCache } from "./types";
import { BadgeComponent } from "./badgeComponent";
import settings from "../settings";


const { View } = RN;

const cache = new Map<string, BadgeCache>();
const REFRESH_INTERVAL = 1000 * 60 * 30;

let unpatch: () => boolean;
let unpatch2: () => boolean;
let cachUser;
export function initBadges() {
const profileBadges = findByName("ProfileBadges", false);
unpatch = after("default", profileBadges, (args, res) => {
let mem = res;

const [, updateForce] = React.useReducer(x => x = !x, false);

const user = args[0]?.user;
if (user === undefined) return;

cachUser = cache.get(user.id);
if (cachUser === undefined) {
fetchbadges(user.id, updateForce);
return;
}

const style = mem?.props?.style

// Credits here to @acquitelol
// https://github.com/enmity-mod/enmity/blob/8ff15a8fffc5a1ad4d41c5e8f8a02e6876a760ec/src/core/patches/badges.tsx#L81-L95
if (!mem) {
mem = <View
style={[style, {
flexDirection: "row",
flexWrap: 'wrap',
alignItems: 'flex-end',
justifyContent: 'flex-end',
paddingVertical: 2
}]}
accessibilityRole={"list"}
accessibilityLabel={"User Badges"}
/>;

mem.props.children = [];
}

const pushBadge = ({ name, image, custom = false }: BadgeProps) => {
const RenderableBadge = () => <BadgeComponent
custom={custom}
name={name}
image={image}
size={Array.isArray(style) ? style?.find(r => r.paddingVertical && r.paddingHorizontal) ? 16 : 22 : 16}
margin={Array.isArray(style) ? 4 : 6}
/>;

// i really dont know what storage.left is...
// update: with 2 minutes of using my brain, its if badges show up on the left or not.
const pushOrUnpush = "PUSH"; // storage.left
if (mem?.props?.badges) pushOrUnpush ? mem.props.badges = [<RenderableBadge />, ...mem.props.badges] : mem.props.badges = [...mem.props.badges, <RenderableBadge />];
else pushOrUnpush ? mem.props.children = [<RenderableBadge />, ...mem.props.children] : mem.props.children = [...mem.props.children, <RenderableBadge />];
};

Object.entries(cachUser?.badges).forEach(([key, value]): any => {

if (settings.tweaks.externalbadges?.valueOf() == false) {
if (key == "opti") return;
}

switch (key) {
case "opti":
if (value?.developer) {
pushBadge({
name: "Opti Developer",
image: "https://raw.githubusercontent.com/Opti-mod/assets/main/BadgeDeveloper.png",
});
}
if (value?.contributor) {
pushBadge({
name: "Opti Contributor",
image: "https://raw.githubusercontent.com/Opti-mod/assets/main/BadgeContributor.png",
});
}
if (value?.supporter) {
pushBadge({
name: "Opti Supporter",
image: "https://raw.githubusercontent.com/Opti-mod/assets/main/BadgeSupporter.png",
});
}
break;
default:
break;
}
})
});
}
export function unloadBadges() {
unpatch?.();
unpatch2?.();
}

async function fetchbadges(userId: string, updateForce: any) {
if (
!cache.has(userId) ||
cache.get(userId)!.lastFetch + REFRESH_INTERVAL < Date.now()
) {

const res = await fetch(
`https://raw.githubusercontent.com/Opti-mod/badges/main/${userId}.json`
);
const body = (await res.json()) as CustomBadges;
const result: BadgeCache =
res.status === 200 || res.status === 404
? { badges: body || {}, lastFetch: Date.now() }
: (cache.delete(userId), { badges: body, lastFetch: Date.now() });

cache.set(userId, result);
updateForce();
}

return cache.get(userId)!.badges;
}
28 changes: 28 additions & 0 deletions src/lib/badge/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export interface CustomBadges {
badge: string;
name: string;
opti: {
developer: boolean;
contributor: boolean;
supporter: boolean;
};
}

export interface BadgeProps {
name: string;
image: string;
custom?: any;
}

export interface BadgeComponents {
name: string;
image: string;
size: number;
margin: number;
custom?: object;
}

export type BadgeCache = {
badges: CustomBadges;
lastFetch: number;
};
1 change: 1 addition & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export const PLUGINS_CHANNEL_ID = "1091880384561684561";
export const THEMES_CHANNEL_ID = "1091880434939482202";
export const GITHUB = "https://github.com/opti-mod/Opti";
export const PROXY_PREFIX = "https://vd-plugins.github.io/proxy";
export const BADGES = 'https://raw.githubusercontent.com/opti-mod/badges/main/';
export const HTTP_REGEX = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$/;
export const HTTP_REGEX_MULTI = /https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;

0 comments on commit 25da11c

Please sign in to comment.