feat : auto-select newly uploaded docs/URLs in my documents list (#5222)
* auto-select newly uploaded docs/URLs in My Documents list * fix: improve auto-select reliability and fix debounce/selection bugs - Add missing `await` on fetchKeys in handleSendLink so loading state and auto-select timing work correctly - Use functional update for setSelectedItems to merge with existing selections instead of replacing them - Stabilize debounced fetchKeys with useRef so rapid uploads actually debounce instead of creating independent timers per render - Rename shadowed local variables (availableDocs -> filteredAvailableDocs) for clarity --------- Co-authored-by: Timothy Carambat <rambat1010@gmail.com>
This commit is contained in:
parent
7ecc4ae005
commit
d767c398c7
@ -1,5 +1,5 @@
|
|||||||
import { CloudArrowUp } from "@phosphor-icons/react";
|
import { CloudArrowUp } from "@phosphor-icons/react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import showToast from "../../../../../utils/toast";
|
import showToast from "../../../../../utils/toast";
|
||||||
import System from "../../../../../models/system";
|
import System from "../../../../../models/system";
|
||||||
@ -34,7 +34,7 @@ export default function UploadFile({
|
|||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
showToast(`Error uploading link: ${data.error}`, "error");
|
showToast(`Error uploading link: ${data.error}`, "error");
|
||||||
} else {
|
} else {
|
||||||
fetchKeys(true);
|
await fetchKeys(true, { autoSelectNew: true });
|
||||||
showToast("Link uploaded successfully", "success");
|
showToast("Link uploaded successfully", "success");
|
||||||
formEl.reset();
|
formEl.reset();
|
||||||
}
|
}
|
||||||
@ -42,11 +42,12 @@ export default function UploadFile({
|
|||||||
setFetchingUrl(false);
|
setFetchingUrl(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Queue all fetchKeys calls through the same debouncer to prevent spamming the server.
|
const debouncedFetchKeysRef = useRef(
|
||||||
// either a success or error will trigger a fetchKeys call so the UI is not stuck loading.
|
debounce((fn, opts) => fn(true, opts), 1000)
|
||||||
const debouncedFetchKeys = debounce(() => fetchKeys(true), 1000);
|
);
|
||||||
const handleUploadSuccess = () => debouncedFetchKeys();
|
const handleUploadSuccess = () =>
|
||||||
const handleUploadError = () => debouncedFetchKeys();
|
debouncedFetchKeysRef.current(fetchKeys, { autoSelectNew: true });
|
||||||
|
const handleUploadError = () => debouncedFetchKeysRef.current(fetchKeys, {});
|
||||||
|
|
||||||
const onDrop = async (acceptedFiles, rejections) => {
|
const onDrop = async (acceptedFiles, rejections) => {
|
||||||
const newAccepted = acceptedFiles.map((file) => {
|
const newAccepted = acceptedFiles.map((file) => {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ArrowsDownUp } from "@phosphor-icons/react";
|
import { ArrowsDownUp } from "@phosphor-icons/react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import Workspace from "../../../../models/workspace";
|
import Workspace from "../../../../models/workspace";
|
||||||
import System from "../../../../models/system";
|
import System from "../../../../models/system";
|
||||||
import showToast from "../../../../utils/toast";
|
import showToast from "../../../../utils/toast";
|
||||||
@ -25,8 +25,23 @@ export default function DocumentSettings({ workspace, systemSettings }) {
|
|||||||
const [movedItems, setMovedItems] = useState([]);
|
const [movedItems, setMovedItems] = useState([]);
|
||||||
const [embeddingsCost, setEmbeddingsCost] = useState(0);
|
const [embeddingsCost, setEmbeddingsCost] = useState(0);
|
||||||
const [loadingMessage, setLoadingMessage] = useState("");
|
const [loadingMessage, setLoadingMessage] = useState("");
|
||||||
|
const availableDocsRef = useRef([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
availableDocsRef.current = availableDocs;
|
||||||
|
}, [availableDocs]);
|
||||||
|
|
||||||
|
async function fetchKeys(refetchWorkspace = false, options = {}) {
|
||||||
|
const { autoSelectNew = false } = options;
|
||||||
|
const previousIds = new Set();
|
||||||
|
if (autoSelectNew && availableDocsRef.current?.items) {
|
||||||
|
for (const folder of availableDocsRef.current.items) {
|
||||||
|
for (const file of folder.items ?? []) {
|
||||||
|
if (file?.id) previousIds.add(file.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchKeys(refetchWorkspace = false) {
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const localFiles = await System.localFiles();
|
const localFiles = await System.localFiles();
|
||||||
const currentWorkspace = refetchWorkspace
|
const currentWorkspace = refetchWorkspace
|
||||||
@ -37,7 +52,7 @@ export default function DocumentSettings({ workspace, systemSettings }) {
|
|||||||
currentWorkspace.documents.map((doc) => doc.docpath) || [];
|
currentWorkspace.documents.map((doc) => doc.docpath) || [];
|
||||||
|
|
||||||
// Documents that are not in the workspace
|
// Documents that are not in the workspace
|
||||||
const availableDocs = {
|
const filteredAvailableDocs = {
|
||||||
...localFiles,
|
...localFiles,
|
||||||
items: localFiles.items.map((folder) => {
|
items: localFiles.items.map((folder) => {
|
||||||
if (folder.items && folder.type === "folder") {
|
if (folder.items && folder.type === "folder") {
|
||||||
@ -56,7 +71,7 @@ export default function DocumentSettings({ workspace, systemSettings }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Documents that are already in the workspace
|
// Documents that are already in the workspace
|
||||||
const workspaceDocs = {
|
const filteredWorkspaceDocs = {
|
||||||
...localFiles,
|
...localFiles,
|
||||||
items: localFiles.items.map((folder) => {
|
items: localFiles.items.map((folder) => {
|
||||||
if (folder.items && folder.type === "folder") {
|
if (folder.items && folder.type === "folder") {
|
||||||
@ -74,8 +89,23 @@ export default function DocumentSettings({ workspace, systemSettings }) {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
setAvailableDocs(availableDocs);
|
setAvailableDocs(filteredAvailableDocs);
|
||||||
setWorkspaceDocs(workspaceDocs);
|
setWorkspaceDocs(filteredWorkspaceDocs);
|
||||||
|
|
||||||
|
if (autoSelectNew) {
|
||||||
|
const newSelected = {};
|
||||||
|
for (const folder of filteredAvailableDocs.items ?? []) {
|
||||||
|
for (const file of folder.items ?? []) {
|
||||||
|
if (file?.id && !previousIds.has(file.id)) {
|
||||||
|
newSelected[file.id] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Object.keys(newSelected).length > 0) {
|
||||||
|
setSelectedItems((prev) => ({ ...prev, ...newSelected }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user