Skip to content
This repository has been archived by the owner on Feb 4, 2024. It is now read-only.

Commit

Permalink
feat: various improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
FedeIlLeone committed Aug 31, 2023
1 parent ddae549 commit 7358d58
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 14 deletions.
35 changes: 29 additions & 6 deletions src/components/EditComposerAttachments.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
import UploadAttachmentActionCreators from "@actions/UploadAttachmentActionCreators";
import ComposerAttachmentPopout from "@components/ComposerAttachmentPopout";
import Popout, { PopoutAlign, PopoutPositions } from "@components/Popout";
import PermissionStore from "@stores/PermissionStore";
import UploadAttachmentStore, { DraftType } from "@stores/UploadAttachmentStore";
import type { Message } from "discord-types/general";
import type React from "react";
import type { Channel, Message } from "discord-types/general";
import { common } from "replugged";
import { MAX_UPLOAD_COUNT } from "../constants";

import "./EditComposerAttachments.css";

const {
constants,
flux: Flux,
fluxDispatcher: Dispatcher,
i18n: { Messages },
React,
} = common;

interface EditComposerAttachmentsProps {
channelId: string;
channel: Channel;
message: Message;
}

export default (props: EditComposerAttachmentsProps): React.ReactElement => {
const { channelId, message } = props;
export default (props: EditComposerAttachmentsProps): React.ReactElement | null => {
const { channel, message } = props;

const channelId = channel.id;

const uploadsCount = Flux.useStateFromStores([UploadAttachmentStore], () => {
return UploadAttachmentStore.getUploadCount(channelId, DraftType.ChannelMessage);
Expand All @@ -31,16 +36,34 @@ export default (props: EditComposerAttachmentsProps): React.ReactElement => {
if (uploadsCount + attachmentsCount > MAX_UPLOAD_COUNT)
UploadAttachmentActionCreators.clearAll(channelId, DraftType.ChannelMessage);

const canAttach = Flux.useStateFromStores([PermissionStore], () => {
return (
channel.isPrivate() ||
(PermissionStore.can(constants.Permissions!.ATTACH_FILES, channel) &&
PermissionStore.can(constants.Permissions!.SEND_MESSAGES, channel))
);
});
if (!canAttach) return null;

const [shouldShow, setShouldShow] = React.useState(false);

Dispatcher.subscribe("UPLOAD_ATTACHMENT_ADD_FILES", () => setShouldShow(true));

return (
<Popout
renderPopout={() => (
<ComposerAttachmentPopout channelId={channelId} attachmentsCount={attachmentsCount} />
)}
position={PopoutPositions.TOP}
align={PopoutAlign.RIGHT}
shouldShow={shouldShow}
onRequestClose={() => setShouldShow(false)}
ignoreModalClicks>
{(props) => (
<a {...props} className="editMessageAttachments-attachmentsCount">
<a
{...props}
onClick={() => setShouldShow(!shouldShow)}
className="editMessageAttachments-attachmentsCount">
{Messages.EDITMESSAGEATTACHMENTS_COUNT_ATTACHMENTS.format({
count: (uploadsCount + attachmentsCount).toString(),
})}
Expand Down
27 changes: 19 additions & 8 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ export const inject = new Injector();
export function _renderEditComposerAttachments(props: MessageEditorProps): React.ReactNode {
const { channel, message } = props;

if (!channel) return null;
if (!channel || !message) return null;

return stopped ? null : <EditComposerAttachments channelId={channel.id} message={message} />;
return stopped ? null : <EditComposerAttachments channel={channel} message={message} />;
}

export function _checkIsInEditor(channelId: string): boolean {
if (!channelId) return false;
return stopped ? false : EditMessageStore.isEditingAny(channelId);
}

Expand All @@ -42,9 +43,13 @@ export function _getEditMessageStore(): typeof EditMessageStore {
export function _checkHasUploads(channelId: string): boolean {
if (!channelId) return false;

return stopped
? false
: UploadAttachmentStore.getUploadCount(channelId, DraftType.ChannelMessage) > 0;
const uploadCount = UploadAttachmentStore.getUploadCount(channelId, DraftType.ChannelMessage);
return stopped ? false : uploadCount > 0;
}

export function _clearUploads(channelId: string): void {
if (!channelId) return;
UploadAttachmentActionCreators.clearAll(channelId, DraftType.ChannelMessage);
}

export async function _patchEditMessageAction(
Expand Down Expand Up @@ -115,22 +120,28 @@ async function patchChannelTextAreaContainer(): Promise<void> {
);
}

const isEditing = Flux.useStateFromStores([EditMessageStore], () => {
return EditMessageStore.isEditingAny(props.channel.id);
});
const isEditing = EditMessageStore.isEditingAny(props.channel.id);
// We don't need to listen to store changes, it re-renders pretty much constantly
if (isEditing && props.type) {
(props.type.submit as Record<string, boolean>).allowEmptyMessage = true;
}
});
}

function patchStartEditMessageAction(): void {
inject.after(messages, "startEditMessage", ([channelId]) => {
UploadAttachmentActionCreators.clearAll(channelId, DraftType.ChannelMessage);
});
}

export { cfg };

export async function start(): Promise<void> {
i18n.loadAllStrings(translations);

await patchDisableableChannelAttachmentArea();
await patchChannelTextAreaContainer();
patchStartEditMessageAction();

stopped = false;
}
Expand Down
5 changes: 5 additions & 0 deletions src/plaintextPatches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ const patches: types.PlaintextPatch[] = [
replace: (_, prefix, ogCheck) =>
`${prefix}!${pluginExports}._checkHasUploads(e.props.channel.id)&&${ogCheck}`,
},
{
// Clear the upload queue when canceling
match: /(onCancel:function\(\){)/,
replace: (_, prefix) => `${prefix}${pluginExports}._clearUploads(e.channel.id);`,
},
],
},
{
Expand Down
70 changes: 70 additions & 0 deletions src/stores/PermissionStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import type { Channel, Guild, Role, User } from "discord-types/general";
import { webpack } from "replugged";
import type { Store } from "replugged/dist/renderer/modules/common/flux";

interface GuildPermissionProps {
canManageBans: boolean;
canManageChannels: boolean;
canManageGuild: boolean;
canManageGuildExpressions: boolean;
canManageNicknames: boolean;
canManageRoles: boolean;
canManageWebhooks: boolean;
canViewAuditLog: boolean;
canViewAuditLogV2: boolean;
canViewGuildAnalytics: boolean;
guild: Guild;
isGuildAdmin: boolean;
isOwner: boolean;
isOwnerWithRequiredMfaLevel: boolean;
}

interface PartialChannelContext {
channelId?: string;
}

interface PartialGuildContext {
guildId?: string;
}

type Context = Channel | Guild | PartialChannelContext | PartialGuildContext;

export interface PermissionStore extends Store {
can: (
permission: bigint,
context: Context,
overwrites?: Channel["permissionOverwrites"],
roles?: Record<string, Role>,
excludeGuildPermissions?: boolean,
) => boolean;
canAccessGuildSettings: (guild: Guild) => boolean;
canBasicChannel: (
permissions: number,
channel: Channel,
overwrites?: Channel["permissionOverwrites"],
roles?: Record<string, Role>,
excludeGuildPermissions?: boolean,
) => boolean;
canImpersonateRole: (guild: Guild, role: Role) => boolean;
canManageUser: (permission: bigint, user: User | string, guild: Guild) => boolean;
canWithPartialContext: (
permission: bigint,
context: PartialChannelContext | PartialGuildContext,
) => boolean;
computeBasicPermissions: (channel: Channel) => number;
computePermissions: (
context: Context,
overwrites?: Channel["permissionOverwrites"],
roles?: Record<string, Role>,
excludeGuildPermissions?: boolean,
) => bigint;
getChannelPermissions: (channel: Channel) => bigint;
getChannelsVersion: () => number;
getGuildPermissionProps: (guild: Guild) => GuildPermissionProps;
getGuildPermissions: (guild: Guild) => bigint;
getGuildVersion: (guildId: string) => number;
getHighestRole: (guild: Guild) => Role | null;
isRoleHigher: (guild: Guild, firstRole: Role | null, secondRole: Role | null) => boolean;
}

export default webpack.getByStoreName<PermissionStore>("PermissionStore")!;

0 comments on commit 7358d58

Please sign in to comment.