Searcher memo and store states

This commit is contained in:
BFlat committed 2024-01-19 17:02:55 +07:00
1 parent 97917cccf0
commit ce28bf84a4
9 files changed
+153 -92

No files matched your search

@@ -1,4 +1,4 @@
import React, { useCallback, useRef, useState } from "react";
import React, { useCallback, useEffect, useRef, useState } from "react";
import Input from "../Input";
import { faSearch } from "@fortawesome/pro-solid-svg-icons";
import MasonryGrid from "../MasonryGrid/MasonryGrid";
@@ -9,6 +9,7 @@ import { SearchWeights } from "@storyteller/components/src/api/weights/SearchWei
import debounce from "lodash.debounce";
import WeightsCards from "../Card/WeightsCards";
import LoadingSpinner from "../LoadingSpinner";
import useSearcherStore from "hooks/useSearcherStore";
interface SearcherProps {
type?: "page" | "modal";
@@ -16,6 +17,7 @@ interface SearcherProps {
weightType?: string;
onResultSelect?: () => void;
weightTypeFilter?: any;
searcherKey: string;
}
export default function Searcher({
@@ -24,18 +26,27 @@ export default function Searcher({
weightType = "all",
onResultSelect,
weightTypeFilter,
searcherKey,
}: SearcherProps) {
const gridContainerRef = useRef<HTMLDivElement | null>(null);
const [searchTerm, setSearchTerm] = useState("");
const { searchTerm, setSearchTerm } = useSearcherStore();
const [foundWeights, setFoundWeights] = useState<Weight[]>([]);
const [isSearching, setIsSearching] = useState(false);
const [searchCompleted, setSearchCompleted] = useState(0);
const bookmarks = useBookmarks();
const ratings = useRatings();
useEffect(() => {
if (searchTerm[searcherKey]) {
setSearchTerm(searcherKey, searchTerm[searcherKey]);
}
doSearch(searchTerm[searcherKey]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const handleInputChange = (e: any) => {
const newValue = e.target.value;
setSearchTerm(newValue);
setSearchTerm(searcherKey, newValue);
debouncedDoSearch(newValue);
};
@@ -79,7 +90,7 @@ export default function Searcher({
<Input
icon={faSearch}
placeholder="Search..."
value={searchTerm}
value={searchTerm[searcherKey]}
onChange={handleInputChange}
className="mb-3"
/>
@@ -92,11 +103,7 @@ export default function Searcher({
{isSearching ? (
<LoadingSpinner />
) : (
<MasonryGrid
key={searchCompleted}
gridRef={gridContainerRef}
onLayoutComplete={() => console.log("Layout complete!")}
>
<MasonryGrid key={searchCompleted} gridRef={gridContainerRef}>
{dataType === "weights" &&
foundWeights.map((data: any, key: number) => {
let props = {
@@ -17,7 +17,7 @@
white-space: nowrap;
justify-content: center;
align-items: center;
min-height: 3rem;
min-height: 46.5px;
padding: 0.75rem;
transition: 0.1s background-color ease-in-out;
font-size: 14px;
@@ -1,76 +1,106 @@
import React, { useState } from "react";
import React, { useState, memo } from "react";
import Searcher from "../Searcher";
import Modal from "../Modal";
import NonRouteTabs from "../Tabs/NonRouteTabs";
import Input from "../Input";
import Button from "../Button";
import useToken from "hooks/useToken";
import { faTrash } from "@fortawesome/free-solid-svg-icons";
interface SelectSearcherProps {
label?: string;
weightTypeFilter?: string;
}
export default function SelectSearcher({
label,
weightTypeFilter,
}: SelectSearcherProps) {
const [isModalOpen, setIsModalOpen] = useState(false);
const { weightTitle } = useToken();
const SelectSearcher = memo(
({ label, weightTypeFilter }: SelectSearcherProps) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const { weightTitle, setWeightTitle } = useToken();
const openModal = () => {
setIsModalOpen(true);
};
const openModal = () => {
setIsModalOpen(true);
};
const closeModal = () => {
setIsModalOpen(false);
};
const closeModal = () => {
setIsModalOpen(false);
};
const searchTabs = [
{
label: "All LoRA Weights",
content: (
<Searcher
type="modal"
onResultSelect={closeModal}
weightTypeFilter={weightTypeFilter}
/>
),
padding: true,
},
{
label: "Bookmarked",
content: <Searcher type="modal" onResultSelect={closeModal} />,
padding: true,
},
];
return (
<>
<div>
{label && <label className="sub-title">{label}</label>}
const handleRemove = () => {
setWeightTitle && setWeightTitle("");
};
<div className="d-flex gap-2">
<Input
disabled={true}
className="w-100"
placeholder="None selected"
value={weightTitle ? weightTitle : ""}
const searchTabs = [
{
label: "All LoRA Weights",
content: (
<Searcher
type="modal"
onResultSelect={closeModal}
weightTypeFilter={weightTypeFilter}
searcherKey="allLoraWeights"
/>
<Button label="Select" onClick={openModal} />
</div>
</div>
),
padding: true,
},
{
label: "Bookmarked",
content: (
<>
<Searcher
type="modal"
onResultSelect={closeModal}
searcherKey="bookmarkedLoraWeights"
/>
<h2 className="text-center py-4">
NEEDS USER BOOKMARK ELASTIC SEARCH HERE
</h2>
</>
),
padding: true,
},
];
return (
<>
<div>
{label && <label className="sub-title">{label}</label>}
<Modal
show={isModalOpen}
handleClose={closeModal}
title="Select a LoRA Weight"
content={() => <NonRouteTabs tabs={searchTabs} />}
showButtons={false}
padding={false}
large={true}
position="top"
mobileFullscreen={true}
/>
</>
);
}
<div className="d-flex gap-2">
<Input
disabled={true}
className="w-100"
placeholder="None selected"
value={weightTitle ? weightTitle : ""}
/>
<Button
label={weightTitle ? "Change" : "Select"}
onClick={openModal}
/>
{weightTitle && (
<Button
square={true}
variant="danger"
icon={faTrash}
onClick={handleRemove}
tooltip="Remove"
/>
)}
</div>
</div>
<Modal
show={isModalOpen}
handleClose={closeModal}
title="Select a LoRA Weight"
content={() => <NonRouteTabs tabs={searchTabs} />}
showButtons={false}
padding={false}
large={true}
position="top"
mobileFullscreen={true}
/>
</>
);
}
);
export default SelectSearcher;
@@ -0,0 +1 @@
export { default } from "./useSearcherStore";
@@ -0,0 +1,21 @@
import { create } from "zustand";
interface SearcherState {
searchTerm: { [searcherKey: string]: string };
}
interface SearcherActions {
setSearchTerm: (searcherKey: string, value: string) => void;
}
type SearcherStore = SearcherState & SearcherActions;
const useSearcherStore = create<SearcherStore>(set => ({
searchTerm: {},
setSearchTerm: (searcherKey, value) =>
set((state: SearcherState) => ({
searchTerm: { ...state.searchTerm, [searcherKey]: value },
})),
}));
export default useSearcherStore;
@@ -431,7 +431,7 @@ styles with important tags:
.form-select {
border-width: 1px;
border-color: $white;
padding: 11px 0.75rem;
padding: 10.25px 0.75rem;
&:focus {
border-color: $primary;
@@ -1719,7 +1719,7 @@ textarea {
}
.fy-studio-frame {
border-radius: .5rem;
border-radius: 0.5rem;
width: 100%;
height: 500px;
}
@@ -770,16 +770,16 @@ class PageContainer extends React.Component<
</Route>
<Route path="/video-mocap/:mediaToken?">
<VideoMocap
{...{
enqueueInferenceJob: this.props.enqueueInferenceJob,
sessionSubscriptionsWrapper:
this.props.sessionSubscriptionsWrapper,
inferenceJobs: this.props.inferenceJobs,
inferenceJobsByCategory: this.props.inferenceJobsByCategory,
}}
/>
</Route>
<VideoMocap
{...{
enqueueInferenceJob: this.props.enqueueInferenceJob,
sessionSubscriptionsWrapper:
this.props.sessionSubscriptionsWrapper,
inferenceJobs: this.props.inferenceJobs,
inferenceJobsByCategory: this.props.inferenceJobsByCategory,
}}
/>
</Route>
<Route path="/character/donald-trump">
<TrumpTtsPage
@@ -10,7 +10,6 @@ import {
} from "@storyteller/components/src/api/media_files/UploadMedia";
import { v4 as uuidv4 } from "uuid";
import { Link } from "react-router-dom";
import SelectSearcher from "components/common/SelectSearcher/SelectSearcher";
interface DevUploadProps {}
@@ -68,10 +67,6 @@ export default function DevUpload(props: DevUploadProps) {
))}
</div>
</Panel>
<div className="mt-5">
<SelectSearcher label="Additional LoRA Weight" />
</div>
</Container>
);
}
@@ -116,13 +116,20 @@ export default function WeightPage({
);
case WeightCategory.VC:
return (
<VcInferencePanel
sessionSubscriptionsWrapper={sessionSubscriptionsWrapper}
enqueueInferenceJob={enqueueInferenceJob}
inferenceJobs={inferenceJobs}
inferenceJobsByCategory={inferenceJobsByCategory}
voiceToken={weight.weight_token}
/>
<>
<VcInferencePanel
sessionSubscriptionsWrapper={sessionSubscriptionsWrapper}
enqueueInferenceJob={enqueueInferenceJob}
inferenceJobs={inferenceJobs}
inferenceJobsByCategory={inferenceJobsByCategory}
voiceToken={weight.weight_token}
/>
<SdInferencePanel
sd_model_token={weight.weight_token}
enqueueInferenceJob={enqueueInferenceJob}
/>
</>
);
case WeightCategory.ZS: