diff --git a/app/src/features/crews/CrewsOverview.tsx b/app/src/features/crews/CrewsOverview.tsx index fe66f7fc..4b9da228 100644 --- a/app/src/features/crews/CrewsOverview.tsx +++ b/app/src/features/crews/CrewsOverview.tsx @@ -10,6 +10,7 @@ import { CountBadge } from "../../ui/Badge"; import { Button } from "../../ui/Button"; import { BotAvatar, moodOf } from "../bots/BotAvatar"; import { CrewDialog } from "./CrewDialog"; +import { orderedCrews, useCrewOrder } from "./crewOrder"; /** Faces shown on a card; the rest are counted. */ const FACES = 6; @@ -18,7 +19,7 @@ const FACES = 6; export function CrewsOverview() { const t = useT(); const words = t.crews.overview; - const crews = useApp(useShallow(crewList)); + const crews = orderedCrews(useApp(useShallow(crewList)), useCrewOrder()); const botCount = useApp((state) => Object.keys(state.bots).length); const [creating, setCreating] = useState(false); return ( diff --git a/app/src/features/crews/Sidebar.tsx b/app/src/features/crews/Sidebar.tsx index feeab6b3..c5a8535e 100644 --- a/app/src/features/crews/Sidebar.tsx +++ b/app/src/features/crews/Sidebar.tsx @@ -1,35 +1,42 @@ -import { ChevronDown, ChevronsDownUp, ChevronsUpDown, Pause, Plus } from "lucide-react"; -import { memo, useCallback, useState } from "react"; +import { + ArrowDown, + ArrowUp, + ChevronDown, + ChevronsDownUp, + ChevronsUpDown, + Pause, + Plus, +} from "lucide-react"; +import { useCallback, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { useShallow } from "zustand/react/shallow"; -import { type Messages, useT } from "../../i18n"; -import { when } from "../../lib/format"; -import { plainText } from "../../lib/plainText"; -import type { Activity, Bot, Crew } from "../../lib/protocol.gen"; -import { activityOf, crewList } from "../../store/app"; +import { useT } from "../../i18n"; +import type { Crew, CrewId } from "../../lib/protocol.gen"; +import { crewList } from "../../store/app"; import { useApp } from "../../store/context"; -import { isUnread, unreadIn } from "../../store/seen"; +import { unreadIn } from "../../store/seen"; import { CountBadge } from "../../ui/Badge"; import { Button } from "../../ui/Button"; import { ContextMenu, menuPoint, type Point } from "../../ui/ContextMenu"; -import { APP_OPENED } from "../../ui/motion"; -import { BotStateBadge, stateView } from "../bots/BotStateBadge"; -import { useBotActions } from "../bots/botActions"; -import { ChiefBadge, isChief } from "../bots/ChiefBadge"; -import { ListAvatar } from "../bots/ListAvatar"; -import { toolAction, toolTitle } from "../chat/toolNames"; import { CrewDialog } from "./CrewDialog"; import { setAllCollapsed, setCollapsed, useCollapsed, useCollapsedSet } from "./collapsed"; import { useCrewActions } from "./crewActions"; +import { moveBy, orderedCrews, setCrewOrder, useCrewOrder } from "./crewOrder"; +import { Conversation } from "./SidebarConversation"; import { row } from "./SidebarPages"; import { StateFilters } from "./StateFilters"; import { filteredBots, useStateFilter } from "./stateFilter"; +import { useCrewDrag } from "./useCrewDrag"; /** Crews as sections and their bots as conversations (spec 15.1). */ export function Sidebar() { const t = useT(); const words = t.crews.sidebar; - const crews = useApp(useShallow(crewList)); + const order = useCrewOrder(); + const crews = orderedCrews(useApp(useShallow(crewList)), order); + const ids = crews.map((crew) => crew.id); + const list = useRef(null); + const drag = useCrewDrag(ids, list); const overview = useApp((state) => state.selectedCrewId === null && !state.page); const selectCrew = useApp((state) => state.selectCrew); const collapsed = useCollapsedSet(); @@ -66,9 +73,9 @@ export function Sidebar() { /> {crews.length > 0 && } -