Skip to content

Commit

Permalink
[extension] Improve drag and drop handling, various fixes (#8707)
Browse files Browse the repository at this point in the history
* Improve drag and drop handling, various fixes

* cleaned params

* lint

* revert extraction changes
  • Loading branch information
tdraier authored Nov 18, 2024
1 parent 7c8d09a commit 568ada6
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 39 deletions.
4 changes: 2 additions & 2 deletions extension/app/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: "add_tab_content",
title: "Add tab content to conversation",
contexts: ["page"],
contexts: ["all"],
});
chrome.contextMenus.create({
id: "add_tab_screenshot",
title: "Add tab screenshot to conversation",
contexts: ["page"],
contexts: ["all"],
});

chrome.contextMenus.create({
Expand Down
56 changes: 45 additions & 11 deletions extension/app/src/components/DropzoneContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
supportedImage,
supportedPlainText,
} from "@dust-tt/client";
import { DropzoneOverlay } from "@dust-tt/sparkle";
import { DropzoneOverlay, useSendNotification } from "@dust-tt/sparkle";
import { useFileDrop } from "@extension/components/conversation/FileUploaderContext";
import { useEffect } from "react";
import { useDropzone } from "react-dropzone";
Expand All @@ -30,6 +30,23 @@ const generateFileName = (blob: Blob) => {
return `${name}${extension}`;
};

const getDroppedUrl = (dataTransfer: DataTransfer) => {
const textHtml = dataTransfer.getData("text/html");
const droppedUrl = dataTransfer.getData("text/uri-list");
if (textHtml) {
const div = document.createElement("div");
div.innerHTML = textHtml;

const url = div.querySelector("img")?.src || div.querySelector("a")?.href;
div.remove();

if (url) {
return url;
}
}
return droppedUrl;
};

export function DropzoneContainer({
children,
description,
Expand All @@ -41,6 +58,8 @@ export function DropzoneContainer({
setDroppedFiles(acceptedFiles);
};

const sendNotification = useSendNotification();

const { getRootProps, isDragActive } = useDropzone({
onDrop,
noClick: true, // Prevent default click behavior.
Expand All @@ -53,23 +72,38 @@ export function DropzoneContainer({
const element = rootProps.ref.current;
const listener = async (e: React.DragEvent) => {
if (e.dataTransfer) {
const droppedUrl = e.dataTransfer.getData("text/uri-list");
const droppedUrl = getDroppedUrl(e.dataTransfer);
if (droppedUrl) {
const response = await fetch(droppedUrl);
const blob = await response.blob();

if (isSupportedFileContentType(blob.type)) {
const filename = droppedUrl.startsWith("data:")
? generateFileName(blob)
: decodeURIComponent(
droppedUrl.split("/").pop() || generateFileName(blob)
);

const filename = droppedUrl.startsWith("data:")
? generateFileName(blob)
: decodeURIComponent(
droppedUrl.split("/").pop() || generateFileName(blob)
);
if (blob.type === "text/html") {
const text = await blob.text();
const div = document.createElement("div");
div.innerHTML = text;
const textBlob = new Blob([div.textContent || ""], {
type: "text/plain",
});
div.remove();
const file = new File([textBlob], `${filename}.txt`, {
type: textBlob.type,
});
onDrop([file]);
} else if (isSupportedFileContentType(blob.type)) {
const file = new File([blob], filename, {
type: blob.type,
});

onDrop([file]);
} else {
sendNotification({
description: "Unsupported file type : " + blob.type,
title: "Unsupported file type",
type: "error",
});
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions extension/app/src/components/input_bar/InputBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ export function AssistantInputBar({
const { agentConfigurations: baseAgentConfigurations } =
usePublicAgentConfigurations();

const fileUploaderService = useFileUploaderService({
owner,
});
const fileUploaderService = useFileUploaderService();

const port = useContext(PortContext);
useEffect(() => {
Expand Down
18 changes: 5 additions & 13 deletions extension/app/src/hooks/useFileUploaderService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type {
ConversationPublicType,
LightWorkspaceType,
Result,
SupportedFileContentType,
} from "@dust-tt/client";
Expand Down Expand Up @@ -50,11 +49,7 @@ export const MAX_FILE_SIZES: Record<"plainText" | "image", number> = {
const COMBINED_MAX_TEXT_FILES_SIZE = MAX_FILE_SIZES["plainText"] * 2;
const COMBINED_MAX_IMAGE_FILES_SIZE = MAX_FILE_SIZES["image"] * 5;

export function useFileUploaderService({
owner,
}: {
owner: LightWorkspaceType;
}) {
export function useFileUploaderService() {
const [fileBlobs, setFileBlobs] = useState<FileBlob[]>([]);
const [isProcessingFiles, setIsProcessingFiles] = useState(false);
const sendNotification = useSendNotification();
Expand Down Expand Up @@ -241,13 +236,10 @@ export function useFileUploaderService({
prevFiles.filter((f) => f.fileId !== fileBlob?.fileId)
);

// Intentionally not awaiting the fetch call to allow it to run asynchronously.
void fetch(`/api/w/${owner.sId}/files/${fileBlob.fileId}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
});
if (fileBlob.fileId) {
// Intentionally not awaiting the fetch call to allow it to run asynchronously.
void dustAPI.deleteFile(fileBlob.fileId);
}

const allFilesReady = fileBlobs.every((f) => f.isUploading === false);
if (allFilesReady && isProcessingFiles) {
Expand Down
7 changes: 2 additions & 5 deletions extension/app/src/pages/RunPage.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import type { LightWorkspaceType } from "@dust-tt/client";
import { Spinner } from "@dust-tt/sparkle";
import { useFileUploaderService } from "@extension/hooks/useFileUploaderService";
import { postConversation } from "@extension/lib/conversation";
import { useDustAPI } from "@extension/lib/dust_api";
import { useEffect } from "react";
import { useLocation, useNavigate } from "react-router";

export const RunPage = ({ workspace }: { workspace: LightWorkspaceType }) => {
export const RunPage = () => {
const navigate = useNavigate();
const location = useLocation();
const dustAPI = useDustAPI();

const fileUploaderService = useFileUploaderService({
owner: workspace,
});
const fileUploaderService = useFileUploaderService();

useEffect(() => {
const run = async () => {
Expand Down
6 changes: 1 addition & 5 deletions extension/app/src/pages/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ export const routes = [
},
{
path: "/run",
element: (
<ProtectedRoute>
{({ workspace }) => <RunPage workspace={workspace} />}
</ProtectedRoute>
),
element: <ProtectedRoute>{() => <RunPage />}</ProtectedRoute>,
},
];
9 changes: 9 additions & 0 deletions sdks/js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,15 @@ export class DustAPI {
return new Ok(fileUploaded);
}

async deleteFile(fileID: string) {
const res = await this.request({
method: "DELETE",
path: `files/${fileID}`,
});

return res;
}

async getActiveMemberEmailsInWorkspace() {
const res = await this.request({
method: "GET",
Expand Down

0 comments on commit 568ada6

Please sign in to comment.