Skip to content

Commit

Permalink
feat: ComposedAttachmentAdapter (#781)
Browse files Browse the repository at this point in the history
  • Loading branch information
Yonom authored Sep 9, 2024
1 parent a22e6bb commit 750fe5f
Showing 1 changed file with 98 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import {
ComposerAttachment,
MessageAttachment,
} from "../../context/stores/Attachment";
import { AttachmentAdapter } from "./AttachmentAdapter";

function fileMatchesAccept(file: File, acceptString: string) {
// Check if the accept string is "*", which allows any file
if (acceptString === "*") {
return true;
}

// Split the accept string into an array of allowed types
const allowedTypes = acceptString
.split(",")
.map((type) => type.trim().toLowerCase());

// Get the file's extension and MIME type
const fileExtension = "." + file.name.split(".").pop()!.toLowerCase();
const fileMimeType = file.type.toLowerCase();

for (const type of allowedTypes) {
// Check for file extension match
if (type.startsWith(".") && type === fileExtension) {
return true;
}

// Check for exact MIME type match
if (type.includes("/") && type === fileMimeType) {
return true;
}

if (type === "image/*" || type === "video/*" || type === "audio/*") {
// Check for wildcard MIME type match
if (type.endsWith("/*")) {
const generalType = type.split("/")[0]!;
if (fileMimeType.startsWith(generalType + "/")) {
return true;
}
}
}
}

return false;
}

export class ComposedAttachmentAdapter implements AttachmentAdapter {
private _adapters: AttachmentAdapter[];

public accept: string;

constructor(adapters: AttachmentAdapter[]) {
this._adapters = adapters;

const wildcardIdx = adapters.findIndex((a) => a.accept === "*");
if (wildcardIdx !== -1) {
if (wildcardIdx !== adapters.length - 1)
throw new Error(
"A wildcard adapter (handling all files) can only be specified as the last adapter.",
);

this.accept = "*";
} else {
this.accept = adapters.map((a) => a.accept).join(",");
}
}

public async add(state: { file: File }): Promise<ComposerAttachment> {
for (const adapter of this._adapters) {
if (fileMatchesAccept(state.file, adapter.accept)) {
return adapter.add(state);
}
}
throw new Error("No matching adapter found for file");
}

public async send(
attachment: ComposerAttachment,
): Promise<MessageAttachment> {
const adapters = this._adapters.slice();
for (const adapter of adapters) {
if (fileMatchesAccept(attachment.file, adapter.accept)) {
return adapter.send(attachment);
}
}
throw new Error("No matching adapter found for attachment");
}

public async remove(attachment: ComposerAttachment): Promise<void> {
const adapters = this._adapters.slice();
for (const adapter of adapters) {
if (fileMatchesAccept(attachment.file, adapter.accept)) {
return adapter.remove(attachment);
}
}
throw new Error("No matching adapter found for attachment");
}
}

0 comments on commit 750fe5f

Please sign in to comment.