11'use client'
22
33import { useCallback , useEffect , useRef , useState } from 'react'
4- import { Check , ChevronDown , ExternalLink , RefreshCw , X } from 'lucide-react'
4+ import { Check , ChevronDown , ExternalLink , RefreshCw } from 'lucide-react'
55import { MicrosoftExcelIcon } from '@/components/icons'
66import { Button } from '@/components/ui/button'
77import {
@@ -281,7 +281,6 @@ export function MicrosoftFileSelector({
281281 ]
282282 : [ ] ,
283283 }
284- setSelectedFile ( fileInfo )
285284 onFileInfoChange ?.( fileInfo )
286285 return fileInfo
287286 }
@@ -309,7 +308,6 @@ export function MicrosoftFileSelector({
309308 mimeType : 'sharepoint/site' ,
310309 webViewLink : site . webUrl ,
311310 }
312- setSelectedFile ( siteInfo )
313311 onFileInfoChange ?.( siteInfo )
314312 return siteInfo
315313 } catch ( error ) {
@@ -433,7 +431,6 @@ export function MicrosoftFileSelector({
433431 modifiedTime : task . createdDateTime ,
434432 }
435433 setSelectedTask ( task )
436- setSelectedFile ( taskAsFileInfo )
437434 onFileInfoChange ?.( taskAsFileInfo )
438435 return taskAsFileInfo
439436 } catch {
@@ -498,7 +495,6 @@ export function MicrosoftFileSelector({
498495
499496 // Update internal state first to avoid race with list refetch
500497 setSelectedFileId ( taskId )
501- setSelectedFile ( taskAsFileInfo )
502498 setSelectedTask ( task )
503499 // Then propagate up
504500 onChange ( taskId , taskAsFileInfo )
@@ -524,81 +520,26 @@ export function MicrosoftFileSelector({
524520
525521 if ( ! selectedCredentialId ) {
526522 // No credentials - clear everything
527- if ( selectedFile ) {
528- setSelectedFile ( null )
529- setSelectedFileId ( '' )
530- onChange ( '' )
531- }
523+ setSelectedFileId ( '' )
524+ onChange ( '' )
532525 // Reset memo when credential is cleared
533526 lastMetaAttemptRef . current = ''
534527 } else if ( prevCredentialId && prevCredentialId !== selectedCredentialId ) {
535- // Credentials changed (not initial load) - clear file info to force refetch
536- if ( selectedFile ) {
537- setSelectedFile ( null )
538- }
539528 // Reset memo when switching credentials
540529 lastMetaAttemptRef . current = ''
541530 }
542- } , [ selectedCredentialId , selectedFile , onChange ] )
531+ } , [ selectedCredentialId , onChange ] )
543532
544- // Fetch the selected file metadata once credentials are loaded or changed
533+ // Keep internal selectedFileId in sync with the value prop
545534 useEffect ( ( ) => {
546- // Fetch metadata when the external value doesn't match our current selectedFile
547- if (
548- value &&
549- selectedCredentialId &&
550- credentialsLoaded &&
551- ( ! selectedFile || selectedFile . id !== value ) &&
552- ! isLoadingSelectedFile
553- ) {
554- // Avoid tight retry loops by memoizing the last attempt tuple
555- const attemptKey = `${ selectedCredentialId } ::${ value } `
556- if ( lastMetaAttemptRef . current === attemptKey ) {
557- return
558- }
559- lastMetaAttemptRef . current = attemptKey
560-
561- if ( serviceId === 'microsoft-planner' ) {
562- void fetchPlannerTaskById ( value )
563- } else {
564- void fetchFileById ( value )
565- }
566- }
567- } , [
568- value ,
569- selectedCredentialId ,
570- credentialsLoaded ,
571- selectedFile ,
572- isLoadingSelectedFile ,
573- fetchFileById ,
574- fetchPlannerTaskById ,
575- serviceId ,
576- ] )
577-
578- // Resolve planner task selection for collaborators
579- useEffect ( ( ) => {
580- if (
581- value &&
582- selectedCredentialId &&
583- credentialsLoaded &&
584- ! selectedTask &&
585- serviceId === 'microsoft-planner'
586- ) {
587- void fetchPlannerTaskById ( value )
535+ if ( value !== selectedFileId ) {
536+ setSelectedFileId ( value )
588537 }
589- } , [
590- value ,
591- selectedCredentialId ,
592- credentialsLoaded ,
593- selectedTask ,
594- serviceId ,
595- fetchPlannerTaskById ,
596- ] )
538+ } , [ value , selectedFileId ] )
597539
598540 // Handle selecting a file from the available files
599541 const handleFileSelect = ( file : MicrosoftFileInfo ) => {
600542 setSelectedFileId ( file . id )
601- setSelectedFile ( file )
602543 onChange ( file . id , file )
603544 onFileInfoChange ?.( file )
604545 setOpen ( false )
@@ -616,7 +557,6 @@ export function MicrosoftFileSelector({
616557 // Clear selection
617558 const handleClearSelection = ( ) => {
618559 setSelectedFileId ( '' )
619- setSelectedFile ( null )
620560 onChange ( '' , undefined )
621561 onFileInfoChange ?.( null )
622562 }
@@ -781,13 +721,6 @@ export function MicrosoftFileSelector({
781721 } )
782722 : availableFiles
783723
784- const canShowPreview = ! ! (
785- showPreview &&
786- selectedFile &&
787- selectedFileId &&
788- selectedFile . id === selectedFileId
789- )
790-
791724 return (
792725 < >
793726 < div className = 'space-y-2' >
@@ -979,68 +912,6 @@ export function MicrosoftFileSelector({
979912 </ PopoverContent >
980913 ) }
981914 </ Popover >
982-
983- { /* File preview */ }
984- { canShowPreview && (
985- < div className = 'relative mt-2 rounded-md border border-muted bg-muted/10 p-2' >
986- < div className = 'absolute top-2 right-2' >
987- < Button
988- variant = 'ghost'
989- size = 'icon'
990- className = 'h-5 w-5 hover:bg-muted'
991- onClick = { handleClearSelection }
992- >
993- < X className = 'h-3 w-3' />
994- </ Button >
995- </ div >
996- < div className = 'flex items-center gap-3 pr-4' >
997- < div className = 'flex h-6 w-6 flex-shrink-0 items-center justify-center rounded bg-muted/20' >
998- { getFileIcon ( selectedFile , 'sm' ) }
999- </ div >
1000- < div className = 'min-w-0 flex-1 overflow-hidden' >
1001- < div className = 'flex items-center gap-2' >
1002- < h4 className = 'truncate font-medium text-xs' > { selectedFile . name } </ h4 >
1003- { selectedFile . modifiedTime && (
1004- < span className = 'whitespace-nowrap text-muted-foreground text-xs' >
1005- { new Date ( selectedFile . modifiedTime ) . toLocaleDateString ( ) }
1006- </ span >
1007- ) }
1008- </ div >
1009- { selectedFile . webViewLink ? (
1010- < a
1011- href = { selectedFile . webViewLink }
1012- target = '_blank'
1013- rel = 'noopener noreferrer'
1014- className = 'flex items-center gap-1 text-foreground text-xs hover:underline'
1015- onClick = { ( e ) => e . stopPropagation ( ) }
1016- >
1017- < span >
1018- { serviceId === 'microsoft-planner'
1019- ? 'Open in Planner'
1020- : serviceId === 'sharepoint'
1021- ? 'Open in SharePoint'
1022- : 'Open in OneDrive' }
1023- </ span >
1024- < ExternalLink className = 'h-3 w-3' />
1025- </ a >
1026- ) : (
1027- < a
1028- href = { `https://graph.microsoft.com/v1.0/me/drive/items/${ selectedFile . id } ` }
1029- target = '_blank'
1030- rel = 'noopener noreferrer'
1031- className = 'flex items-center gap-1 text-foreground text-xs hover:underline'
1032- onClick = { ( e ) => e . stopPropagation ( ) }
1033- >
1034- < span >
1035- { serviceId === 'sharepoint' ? 'Open in SharePoint' : 'Open in OneDrive' }
1036- </ span >
1037- < ExternalLink className = 'h-3 w-3' />
1038- </ a >
1039- ) }
1040- </ div >
1041- </ div >
1042- </ div >
1043- ) }
1044915 </ div >
1045916
1046917 { showOAuthModal && (
0 commit comments