Skip to content

Commit

Permalink
feat: add drag/drop model preference feature
Browse files Browse the repository at this point in the history
  • Loading branch information
zmh-program committed Jan 4, 2024
1 parent cf4f3ae commit aef89ba
Show file tree
Hide file tree
Showing 12 changed files with 217 additions and 65 deletions.
1 change: 1 addition & 0 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"@tauri-apps/cli": "^1.5.6",
"@types/node": "^20.5.9",
"@types/react": "^18.2.15",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-dom": "^18.2.7",
"@types/react-syntax-highlighter": "^15.5.7",
"@typescript-eslint/eslint-plugin": "^6.0.0",
Expand Down
9 changes: 9 additions & 0 deletions app/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions app/src/api/broadcast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ export type CreateBroadcastResponse = {
export async function getRawBroadcast(): Promise<Broadcast> {
try {
const data = await axios.get("/broadcast/view");
return data.data as Broadcast;
if (data.data) return data.data as Broadcast;
} catch (e) {
console.warn(e);
return {
content: "",
index: 0,
};
}

return {
content: "",
index: 0,
};
}

export async function getBroadcast(): Promise<string> {
Expand Down
1 change: 1 addition & 0 deletions app/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export type Model = {
name: string;
free: boolean;
auth: boolean;
high_context: boolean;
tag?: string[];
};

Expand Down
26 changes: 19 additions & 7 deletions app/src/assets/pages/home.less
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
overflow: auto;
scrollbar-width: thin;

.market-wrapper {
width: 100%;
height: 100%;
max-width: 768px;
margin: 0 auto;
}

@media (max-width: 768px) {
padding: 1rem;
}
Expand Down Expand Up @@ -71,8 +78,7 @@

.model-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
flex-direction: column;
width: 100%;
}

Expand All @@ -88,14 +94,11 @@
border: 1px solid hsl(var(--border-hover));
border-radius: var(--radius);
transition: 0.25s;
transition-property: border-color, padding, background, box-shadow;
cursor: grab;
animation: fadein 0.25s forwards ease-in-out;
opacity: 0;
width: 100%;

@media (min-width: 960px) {
width: calc(50% - 1rem);
}
width: calc(100% - 1rem);

@keyframes fadein {
from { opacity: 0; transform: translateY(2.5rem); }
Expand All @@ -109,6 +112,10 @@
&:before {
width: 100%;
}

.grip-icon {
opacity: 1;
}
}

&.active {
Expand All @@ -132,6 +139,11 @@
border-radius: var(--radius);
}

.grip-icon {
opacity: 0.6;
transition: 0.25s;
}

.model-avatar {
border-radius: var(--radius);
width: 3rem;
Expand Down
7 changes: 2 additions & 5 deletions app/src/components/FileProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { useDraggableInput } from "@/utils/dom.ts";
import { FileObject, FileArray, blobParser } from "@/api/file.ts";
import { Button } from "@/components/ui/button.tsx";
import { useSelector } from "react-redux";
import { largeContextModels } from "@/conf.ts";
import { isHighContextModel } from "@/conf.ts";
import { selectModel } from "@/store/chat.ts";
import { ChatAction } from "@/components/home/assemblies/ChatAction.tsx";

Expand All @@ -45,10 +45,7 @@ function FileProvider({ value, onChange }: FileProviderProps) {
console.debug(
`[file] new file was added (filename: ${file.name}, size: ${file.size}, prompt: ${file.content.length})`,
);
if (
file.content.length > MaxPromptSize &&
!largeContextModels.includes(model)
) {
if (file.content.length > MaxPromptSize && isHighContextModel(model)) {
file.content = file.content.slice(0, MaxPromptSize);
toast({
title: t("file.max-length"),
Expand Down
8 changes: 1 addition & 7 deletions app/src/components/home/ModelFinder.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import SelectGroup, { SelectItemProps } from "@/components/SelectGroup.tsx";
import { expensiveModels, supportModels } from "@/conf.ts";
import { supportModels } from "@/conf.ts";
import {
getPlanModels,
openMarket,
Expand Down Expand Up @@ -35,12 +35,6 @@ function filterModel(model: Model, level: number) {
value: model.name,
badge: { variant: "gold", name: "plus" },
} as SelectItemProps;
} else if (expensiveModels.includes(model.id)) {
return {
name: model.id,
value: model.name,
badge: { variant: "gold", name: "expensive" },
} as SelectItemProps;
}

return {
Expand Down
102 changes: 85 additions & 17 deletions app/src/components/home/ModelMarket.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Input } from "@/components/ui/input.tsx";
import {
ChevronLeft,
ChevronRight,
GripVertical,
Link,
Plus,
Search,
Expand Down Expand Up @@ -31,6 +32,13 @@ import { selectAuthenticated } from "@/store/auth.ts";
import { useToast } from "@/components/ui/use-toast.ts";
import { docsEndpoint } from "@/utils/env.ts";
import { goAuth } from "@/utils/app.ts";
import {
DragDropContext,
Droppable,
Draggable,
DropResult,
} from "react-beautiful-dnd";
import { savePreferenceModels } from "@/utils/storage.ts";

type SearchBarProps = {
value: string;
Expand Down Expand Up @@ -58,13 +66,23 @@ function SearchBar({ value, onChange }: SearchBarProps) {
);
}

type ModelProps = {
type ModelProps = React.DetailedHTMLProps<
React.HTMLAttributes<HTMLDivElement>,
HTMLDivElement
> & {
model: Model;
className?: string;
style?: React.CSSProperties;
forwardRef?: React.Ref<HTMLDivElement>;
};

function ModelItem({ model, className, style }: ModelProps) {
function ModelItem({
model,
className,
style,
forwardRef,
...props
}: ModelProps) {
const { t } = useTranslation();
const dispatch = useDispatch();
const { toast } = useToast();
Expand Down Expand Up @@ -94,6 +112,8 @@ function ModelItem({ model, className, style }: ModelProps) {
<div
className={`model-item ${className}`}
style={style}
ref={forwardRef}
{...props}
onClick={() => {
dispatch(addModelList(model.id));

Expand All @@ -113,6 +133,7 @@ function ModelItem({ model, className, style }: ModelProps) {
dispatch(closeMarket());
}}
>
<GripVertical className={`grip-icon h-4 w-4 translate-x-[-1rem]`} />
<img className={`model-avatar`} src={avatar} alt={model.name} />
<div className={`model-info`}>
<p className={`model-name ${pro ? "pro" : ""}`}>{model.name}</p>
Expand Down Expand Up @@ -163,7 +184,7 @@ function MarketPlace({ search }: MarketPlaceProps) {
const { t } = useTranslation();
const select = useSelector(selectModel);

const arr = useMemo(() => {
const models = useMemo(() => {
if (search.length === 0) return supportModels;
// fuzzy search
const raw = splitList(search.toLowerCase(), [" ", ",", ";", "-"]);
Expand All @@ -181,18 +202,63 @@ function MarketPlace({ search }: MarketPlaceProps) {
tag_translated.includes(item),
);
});
}, [search]);
}, [supportModels, search]);

const queryIndex = (id: number) => {
const model = models[id];
if (!model) return -1;

return supportModels.findIndex((item) => item.id === model.id);
};

const onDragEnd = (result: DropResult) => {
const { destination, source } = result;
if (
!destination ||
destination.index === source.index ||
destination.index === -1
)
return;

const from = queryIndex(source.index);
const to = queryIndex(destination.index);
if (from === -1 || to === -1) return;

const list = [...supportModels];
const [removed] = list.splice(from, 1);
list.splice(to, 0, removed);

supportModels.splice(0, supportModels.length, ...list);
savePreferenceModels(supportModels);
};

return (
<div className={`model-list`}>
{arr.map((model, index) => (
<ModelItem
model={model}
key={index}
className={`${select === model.id ? "active" : ""}`}
/>
))}
</div>
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId={`model-market`}>
{(provided) => (
<div
className={`model-list`}
{...provided.droppableProps}
ref={provided.innerRef}
>
{models.map((model, index) => (
<Draggable key={model.id} draggableId={model.id} index={index}>
{(provided) => (
<ModelItem
model={model}
className={`${select === model.id ? "active" : ""}`}
forwardRef={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
/>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
}

Expand Down Expand Up @@ -237,10 +303,12 @@ function ModelMarket() {

return (
<div className={`model-market`}>
<MarketHeader />
<SearchBar value={search} onChange={setSearch} />
<MarketPlace search={search} />
<MarketFooter />
<div className={`market-wrapper`}>
<MarketHeader />
<SearchBar value={search} onChange={setSearch} />
<MarketPlace search={search} />
<MarketFooter />
</div>
</div>
);
}
Expand Down
Loading

0 comments on commit aef89ba

Please sign in to comment.