22
33import { memo , useCallback , useEffect , useLayoutEffect , useMemo , useRef , useState } from 'react'
44import { createLogger } from '@sim/logger'
5- import { Compass , MoreHorizontal } from 'lucide-react'
5+ import { Compass , MoreHorizontal , Pin } from 'lucide-react'
66import Image from 'next/image'
77import Link from 'next/link'
88import { useParams , usePathname , useRouter } from 'next/navigation'
@@ -91,6 +91,7 @@ import {
9191 useMarkTaskRead ,
9292 useMarkTaskUnread ,
9393 useRenameTask ,
94+ useSetTaskPinned ,
9495 useTasks ,
9596} from '@/hooks/queries/tasks'
9697import { useUpdateWorkflow } from '@/hooks/queries/workflows'
@@ -144,6 +145,7 @@ const SidebarTaskItem = memo(function SidebarTaskItem({
144145 isSelected,
145146 isActive,
146147 isUnread,
148+ isPinned,
147149 isMenuOpen,
148150 showCollapsedTooltips,
149151 onMultiSelectClick,
@@ -156,6 +158,7 @@ const SidebarTaskItem = memo(function SidebarTaskItem({
156158 isSelected : boolean
157159 isActive : boolean
158160 isUnread : boolean
161+ isPinned : boolean
159162 isMenuOpen : boolean
160163 showCollapsedTooltips : boolean
161164 onMultiSelectClick : ( taskId : string , shiftKey : boolean ) => void
@@ -219,6 +222,9 @@ const SidebarTaskItem = memo(function SidebarTaskItem({
219222 { ! isActive && isUnread && ! isCurrentRoute && ! isMenuOpen && (
220223 < span className = 'absolute size-[7px] rounded-full bg-[var(--brand-accent)] group-hover:hidden' />
221224 ) }
225+ { ! isActive && ! isUnread && isPinned && ! isCurrentRoute && ! isMenuOpen && (
226+ < Pin className = 'absolute size-[12px] text-[var(--text-icon)] group-hover:hidden' />
227+ ) }
222228 < button
223229 type = 'button'
224230 aria-label = 'Task options'
@@ -581,6 +587,7 @@ export const Sidebar = memo(function Sidebar() {
581587 const deleteTasksMutation = useDeleteTasks ( workspaceId )
582588 const markTaskReadMutation = useMarkTaskRead ( workspaceId )
583589 const markTaskUnreadMutation = useMarkTaskUnread ( workspaceId )
590+ const setTaskPinnedMutation = useSetTaskPinned ( workspaceId )
584591 const renameTaskMutation = useRenameTask ( workspaceId )
585592 const tasksHover = useHoverMenu ( )
586593 const workflowsHover = useHoverMenu ( )
@@ -790,6 +797,10 @@ export const Sidebar = memo(function Sidebar() {
790797 : [ ] ,
791798 [ fetchedTasks , workspaceId ]
792799 )
800+ const tasksRef = useRef ( tasks )
801+ useEffect ( ( ) => {
802+ tasksRef . current = tasks
803+ } , [ tasks ] )
793804
794805 const { data : fetchedTables = [ ] } = useTablesList ( workspaceId )
795806 const { data : fetchedFiles = [ ] } = useWorkspaceFiles ( workspaceId )
@@ -930,6 +941,15 @@ export const Sidebar = memo(function Sidebar() {
930941 markTaskUnreadMutation . mutate ( ids [ 0 ] )
931942 } , [ ] )
932943
944+ const handleToggleTaskPin = useCallback ( ( ) => {
945+ const { taskIds : ids } = contextMenuSelectionRef . current
946+ if ( ids . length !== 1 ) return
947+ const taskId = ids [ 0 ]
948+ const task = tasksRef . current . find ( ( t ) => t . id === taskId )
949+ if ( ! task ) return
950+ setTaskPinnedMutation . mutate ( { chatId : taskId , pinned : ! task . isPinned } )
951+ } , [ ] )
952+
933953 const handleStartTaskRename = useCallback ( ( ) => {
934954 const { taskIds : ids } = contextMenuSelectionRef . current
935955 if ( ids . length !== 1 ) return
@@ -998,12 +1018,6 @@ export const Sidebar = memo(function Sidebar() {
9981018 } )
9991019 } , [ workflowId , workflowsLoading ] )
10001020
1001- useEffect ( ( ) => {
1002- if ( ! isOnWorkflowPage && ! isCollapsed ) {
1003- setSidebarWidth ( SIDEBAR_WIDTH . MIN )
1004- }
1005- } , [ isOnWorkflowPage , isCollapsed , setSidebarWidth ] )
1006-
10071021 const handleCreateWorkflow = useCallback ( async ( ) => {
10081022 const workflowId = await createWorkflow ( )
10091023 if ( workflowId ) {
@@ -1521,6 +1535,7 @@ export const Sidebar = memo(function Sidebar() {
15211535 isSelected = { isSelected }
15221536 isActive = { ! ! task . isActive }
15231537 isUnread = { ! ! task . isUnread }
1538+ isPinned = { ! ! task . isPinned }
15241539 isMenuOpen = { menuOpenTaskId === task . id }
15251540 showCollapsedTooltips = { showCollapsedTooltips }
15261541 onMultiSelectClick = { handleTaskClick }
@@ -1771,6 +1786,7 @@ export const Sidebar = memo(function Sidebar() {
17711786 onOpenInNewTab = { handleTaskOpenInNewTab }
17721787 onMarkAsRead = { handleMarkTaskAsRead }
17731788 onMarkAsUnread = { handleMarkTaskAsUnread }
1789+ onTogglePin = { handleToggleTaskPin }
17741790 onRename = { handleStartTaskRename }
17751791 onDelete = { handleDeleteTask }
17761792 showOpenInNewTab = { ! isMultiTaskContextMenu }
@@ -1780,6 +1796,8 @@ export const Sidebar = memo(function Sidebar() {
17801796 ! ! activeTaskContextMenuItem &&
17811797 ! activeTaskContextMenuItem . isUnread
17821798 }
1799+ showPin = { ! isMultiTaskContextMenu && ! ! activeTaskContextMenuItem }
1800+ isPinned = { ! ! activeTaskContextMenuItem ?. isPinned }
17831801 showRename = { ! isMultiTaskContextMenu }
17841802 showDuplicate = { false }
17851803 showColorChange = { false }
@@ -1800,21 +1818,19 @@ export const Sidebar = memo(function Sidebar() {
18001818 </ div >
18011819 </ aside >
18021820
1803- { ( isCollapsed || isOnWorkflowPage ) && (
1804- < div
1805- className = { cn (
1806- 'absolute top-0 right-0 bottom-0 z-20 w-[8px] translate-x-1/2' ,
1807- isCollapsed ? 'cursor-e-resize' : 'cursor-ew-resize'
1808- ) }
1809- onMouseDown = { isCollapsed ? undefined : handleMouseDown }
1810- onClick = { isCollapsed ? toggleCollapsed : undefined }
1811- onKeyDown = { handleEdgeKeyDown }
1812- role = { isCollapsed ? 'button' : 'separator' }
1813- tabIndex = { 0 }
1814- aria-orientation = { isCollapsed ? undefined : 'vertical' }
1815- aria-label = { isCollapsed ? 'Expand sidebar' : 'Resize sidebar' }
1816- />
1817- ) }
1821+ < div
1822+ className = { cn (
1823+ 'absolute top-0 right-0 bottom-0 z-20 w-[8px] translate-x-1/2' ,
1824+ isCollapsed ? 'cursor-e-resize' : 'cursor-ew-resize'
1825+ ) }
1826+ onMouseDown = { isCollapsed ? undefined : handleMouseDown }
1827+ onClick = { isCollapsed ? toggleCollapsed : undefined }
1828+ onKeyDown = { handleEdgeKeyDown }
1829+ role = { isCollapsed ? 'button' : 'separator' }
1830+ tabIndex = { 0 }
1831+ aria-orientation = { isCollapsed ? undefined : 'vertical' }
1832+ aria-label = { isCollapsed ? 'Expand sidebar' : 'Resize sidebar' }
1833+ />
18181834 </ div >
18191835
18201836 < SearchModal
0 commit comments