Skip to content

Commit

Permalink
Merge branch 'dev' into fix-client-theme-for-visual-refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
NSPC911 authored Jan 28, 2025
2 parents 03f56cc + d6141cd commit f3f1470
Show file tree
Hide file tree
Showing 58 changed files with 1,118 additions and 1,244 deletions.
8 changes: 7 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,13 @@ export default tseslint.config(
"no-invalid-regexp": "error",
"no-constant-condition": ["error", { "checkLoops": false }],
"no-duplicate-imports": "error",
"dot-notation": "error",
"@typescript-eslint/dot-notation": [
"error",
{
"allowPrivateClassPropertyAccess": true,
"allowProtectedClassPropertyAccess": true
}
],
"no-useless-escape": [
"error",
{
Expand Down
21 changes: 2 additions & 19 deletions src/api/Badges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const Badges = new Set<ProfileBadge>();
* Register a new badge with the Badges API
* @param badge The badge to register
*/
export function addBadge(badge: ProfileBadge) {
export function addProfileBadge(badge: ProfileBadge) {
badge.component &&= ErrorBoundary.wrap(badge.component, { noop: true });
Badges.add(badge);
}
Expand All @@ -66,7 +66,7 @@ export function addBadge(badge: ProfileBadge) {
* Unregister a badge from the Badges API
* @param badge The badge to remove
*/
export function removeBadge(badge: ProfileBadge) {
export function removeProfileBadge(badge: ProfileBadge) {
return Badges.delete(badge);
}

Expand Down Expand Up @@ -100,20 +100,3 @@ export interface BadgeUserArgs {
userId: string;
guildId: string;
}

interface ConnectedAccount {
type: string;
id: string;
name: string;
verified: boolean;
}

interface Profile {
connectedAccounts: ConnectedAccount[];
premiumType: number;
premiumSince: string;
premiumGuildSince?: any;
lastFetched: number;
profileFetchFailed: boolean;
application?: any;
}
6 changes: 3 additions & 3 deletions src/api/ChatButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ export interface ChatBarProps {
};
}

export type ChatBarButton = (props: ChatBarProps & { isMainChat: boolean; }) => JSX.Element | null;
export type ChatBarButtonFactory = (props: ChatBarProps & { isMainChat: boolean; }) => JSX.Element | null;

const buttonFactories = new Map<string, ChatBarButton>();
const buttonFactories = new Map<string, ChatBarButtonFactory>();
const logger = new Logger("ChatButtons");

export function _injectButtons(buttons: ReactNode[], props: ChatBarProps) {
Expand All @@ -91,7 +91,7 @@ export function _injectButtons(buttons: ReactNode[], props: ChatBarProps) {
}
}

export const addChatBarButton = (id: string, button: ChatBarButton) => buttonFactories.set(id, button);
export const addChatBarButton = (id: string, button: ChatBarButtonFactory) => buttonFactories.set(id, button);
export const removeChatBarButton = (id: string) => buttonFactories.delete(id);

export interface ChatBarButtonProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import ErrorBoundary from "@components/ErrorBoundary";
import { Channel, User } from "discord-types/general/index.js";
import { JSX } from "react";

Expand All @@ -39,27 +40,32 @@ interface DecoratorProps {
user: User;
[key: string]: any;
}
export type Decorator = (props: DecoratorProps) => JSX.Element | null;
export type MemberListDecoratorFactory = (props: DecoratorProps) => JSX.Element | null;
type OnlyIn = "guilds" | "dms";

export const decorators = new Map<string, { decorator: Decorator, onlyIn?: OnlyIn; }>();
export const decorators = new Map<string, { render: MemberListDecoratorFactory, onlyIn?: OnlyIn; }>();

export function addDecorator(identifier: string, decorator: Decorator, onlyIn?: OnlyIn) {
decorators.set(identifier, { decorator, onlyIn });
export function addMemberListDecorator(identifier: string, render: MemberListDecoratorFactory, onlyIn?: OnlyIn) {
decorators.set(identifier, { render, onlyIn });
}

export function removeDecorator(identifier: string) {
export function removeMemberListDecorator(identifier: string) {
decorators.delete(identifier);
}

export function __getDecorators(props: DecoratorProps): (JSX.Element | null)[] {
const isInGuild = !!(props.guildId);
return Array.from(decorators.values(), decoratorObj => {
const { decorator, onlyIn } = decoratorObj;
// this can most likely be done cleaner
if (!onlyIn || (onlyIn === "guilds" && isInGuild) || (onlyIn === "dms" && !isInGuild)) {
return decorator(props);
return Array.from(
decorators.entries(),
([key, { render: Decorator, onlyIn }]) => {
if ((onlyIn === "guilds" && !isInGuild) || (onlyIn === "dms" && isInGuild))
return null;

return (
<ErrorBoundary noop key={key} message={`Failed to render ${key} Member List Decorator`}>
<Decorator {...props} />
</ErrorBoundary>
);
}
return null;
});
);
}
36 changes: 17 additions & 19 deletions src/api/MessageAccessories.ts → src/api/MessageAccessories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,42 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import { JSX } from "react";
import ErrorBoundary from "@components/ErrorBoundary";
import { JSX, ReactNode } from "react";

export type AccessoryCallback = (props: Record<string, any>) => JSX.Element | null | Array<JSX.Element | null>;
export type Accessory = {
callback: AccessoryCallback;
export type MessageAccessoryFactory = (props: Record<string, any>) => ReactNode;
export type MessageAccessory = {
render: MessageAccessoryFactory;
position?: number;
};

export const accessories = new Map<String, Accessory>();
export const accessories = new Map<string, MessageAccessory>();

export function addAccessory(
export function addMessageAccessory(
identifier: string,
callback: AccessoryCallback,
render: MessageAccessoryFactory,
position?: number
) {
accessories.set(identifier, {
callback,
render,
position,
});
}

export function removeAccessory(identifier: string) {
export function removeMessageAccessory(identifier: string) {
accessories.delete(identifier);
}

export function _modifyAccessories(
elements: JSX.Element[],
props: Record<string, any>
) {
for (const accessory of accessories.values()) {
let accessories = accessory.callback(props);
if (accessories == null)
continue;

if (!Array.isArray(accessories))
accessories = [accessories];
else if (accessories.length === 0)
continue;
for (const [key, accessory] of accessories.entries()) {
const res = (
<ErrorBoundary message={`Failed to render ${key} Message Accessory`} key={key}>
<accessory.render {...props} />
</ErrorBoundary>
);

elements.splice(
accessory.position != null
Expand All @@ -62,7 +60,7 @@ export function _modifyAccessories(
: accessory.position
: elements.length,
0,
...accessories.filter(e => e != null) as JSX.Element[]
res
);
}

Expand Down
24 changes: 15 additions & 9 deletions src/api/MessageDecorations.ts → src/api/MessageDecorations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import ErrorBoundary from "@components/ErrorBoundary";
import { Channel, Message } from "discord-types/general/index.js";
import { JSX } from "react";

interface DecorationProps {
export interface MessageDecorationProps {
author: {
/**
* Will be username if the user has no nickname
Expand All @@ -45,20 +46,25 @@ interface DecorationProps {
message: Message;
[key: string]: any;
}
export type Decoration = (props: DecorationProps) => JSX.Element | null;
export type MessageDecorationFactory = (props: MessageDecorationProps) => JSX.Element | null;

export const decorations = new Map<string, Decoration>();
export const decorations = new Map<string, MessageDecorationFactory>();

export function addDecoration(identifier: string, decoration: Decoration) {
export function addMessageDecoration(identifier: string, decoration: MessageDecorationFactory) {
decorations.set(identifier, decoration);
}

export function removeDecoration(identifier: string) {
export function removeMessageDecoration(identifier: string) {
decorations.delete(identifier);
}

export function __addDecorationsToMessage(props: DecorationProps): (JSX.Element | null)[] {
return [...decorations.values()].map(decoration => {
return decoration(props);
});
export function __addDecorationsToMessage(props: MessageDecorationProps): (JSX.Element | null)[] {
return Array.from(
decorations.entries(),
([key, Decoration]) => (
<ErrorBoundary noop message={`Failed to render ${key} Message Decoration`} key={key}>
<Decoration {...props} />
</ErrorBoundary>
)
);
}
24 changes: 12 additions & 12 deletions src/api/MessageEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ export interface MessageExtra {
openWarningPopout: (props: any) => any;
}

export type SendListener = (channelId: string, messageObj: MessageObject, extra: MessageExtra) => Promisable<void | { cancel: boolean; }>;
export type EditListener = (channelId: string, messageId: string, messageObj: MessageObject) => Promisable<void | { cancel: boolean; }>;
export type MessageSendListener = (channelId: string, messageObj: MessageObject, extra: MessageExtra) => Promisable<void | { cancel: boolean; }>;
export type MessageEditListener = (channelId: string, messageId: string, messageObj: MessageObject) => Promisable<void | { cancel: boolean; }>;

const sendListeners = new Set<SendListener>();
const editListeners = new Set<EditListener>();
const sendListeners = new Set<MessageSendListener>();
const editListeners = new Set<MessageEditListener>();

export async function _handlePreSend(channelId: string, messageObj: MessageObject, extra: MessageExtra, replyOptions: MessageReplyOptions) {
extra.replyOptions = replyOptions;
Expand Down Expand Up @@ -111,29 +111,29 @@ export async function _handlePreEdit(channelId: string, messageId: string, messa
/**
* Note: This event fires off before a message is sent, allowing you to edit the message.
*/
export function addPreSendListener(listener: SendListener) {
export function addMessagePreSendListener(listener: MessageSendListener) {
sendListeners.add(listener);
return listener;
}
/**
* Note: This event fires off before a message's edit is applied, allowing you to further edit the message.
*/
export function addPreEditListener(listener: EditListener) {
export function addMessagePreEditListener(listener: MessageEditListener) {
editListeners.add(listener);
return listener;
}
export function removePreSendListener(listener: SendListener) {
export function removeMessagePreSendListener(listener: MessageSendListener) {
return sendListeners.delete(listener);
}
export function removePreEditListener(listener: EditListener) {
export function removeMessagePreEditListener(listener: MessageEditListener) {
return editListeners.delete(listener);
}


// Message clicks
type ClickListener = (message: Message, channel: Channel, event: MouseEvent) => void;
export type MessageClickListener = (message: Message, channel: Channel, event: MouseEvent) => void;

const listeners = new Set<ClickListener>();
const listeners = new Set<MessageClickListener>();

export function _handleClick(message: Message, channel: Channel, event: MouseEvent) {
// message object may be outdated, so (try to) fetch latest one
Expand All @@ -147,11 +147,11 @@ export function _handleClick(message: Message, channel: Channel, event: MouseEve
}
}

export function addClickListener(listener: ClickListener) {
export function addMessageClickListener(listener: MessageClickListener) {
listeners.add(listener);
return listener;
}

export function removeClickListener(listener: ClickListener) {
export function removeMessageClickListener(listener: MessageClickListener) {
return listeners.delete(listener);
}
14 changes: 7 additions & 7 deletions src/api/MessagePopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import type { ComponentType, MouseEventHandler } from "react";

const logger = new Logger("MessagePopover");

export interface ButtonItem {
export interface MessagePopoverButtonItem {
key?: string,
label: string,
icon: ComponentType<any>,
Expand All @@ -33,23 +33,23 @@ export interface ButtonItem {
onContextMenu?: MouseEventHandler<HTMLButtonElement>;
}

export type getButtonItem = (message: Message) => ButtonItem | null;
export type MessagePopoverButtonFactory = (message: Message) => MessagePopoverButtonItem | null;

export const buttons = new Map<string, getButtonItem>();
export const buttons = new Map<string, MessagePopoverButtonFactory>();

export function addButton(
export function addMessagePopoverButton(
identifier: string,
item: getButtonItem,
item: MessagePopoverButtonFactory,
) {
buttons.set(identifier, item);
}

export function removeButton(identifier: string) {
export function removeMessagePopoverButton(identifier: string) {
buttons.delete(identifier);
}

export function _buildPopoverElements(
Component: React.ComponentType<ButtonItem>,
Component: React.ComponentType<MessagePopoverButtonItem>,
message: Message
) {
const items: React.ReactNode[] = [];
Expand Down
Loading

0 comments on commit f3f1470

Please sign in to comment.