@@ -159,17 +159,20 @@ export class OneDriveHandler {
159159 private clientId : string ;
160160 private provider : CloudProvider ;
161161 private baseUrl ?: string ;
162+ private onPickerStateChange ?: ( isOpen : boolean ) => void ;
162163
163164 constructor (
164165 accessToken : string ,
165166 clientId : string ,
166167 provider : CloudProvider = "onedrive" ,
167168 baseUrl ?: string ,
169+ onPickerStateChange ?: ( isOpen : boolean ) => void ,
168170 ) {
169171 this . accessToken = accessToken ;
170172 this . clientId = clientId ;
171173 this . provider = provider ;
172174 this . baseUrl = baseUrl ;
175+ this . onPickerStateChange = onPickerStateChange ;
173176 }
174177
175178 async loadPickerApi ( ) : Promise < boolean > {
@@ -206,57 +209,111 @@ export class OneDriveHandler {
206209 console . log ( "OneDrive picker success callback:" , response ) ;
207210 if ( ! response || ! response . value ) {
208211 console . warn ( "OneDrive picker returned no value" ) ;
212+ this . onPickerStateChange ?.( false ) ;
209213 return ;
210214 }
211215
212- const newFiles : CloudFile [ ] =
213- response . value ?. map ( ( item : any ) => {
214- // Extract mimeType from file object or infer from name
215- let mimeType = item . file ?. mimeType ;
216- if ( ! mimeType && item . name ) {
217- // Infer from extension if mimeType not provided
218- const ext = item . name . split ( "." ) . pop ( ) ?. toLowerCase ( ) ;
219- const mimeTypes : { [ key : string ] : string } = {
220- pdf : "application/pdf" ,
221- doc : "application/msword" ,
222- docx : "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ,
223- xls : "application/vnd.ms-excel" ,
224- xlsx : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ,
225- ppt : "application/vnd.ms-powerpoint" ,
226- pptx : "application/vnd.openxmlformats-officedocument.presentationml.presentation" ,
227- txt : "text/plain" ,
228- csv : "text/csv" ,
229- json : "application/json" ,
230- xml : "application/xml" ,
231- html : "text/html" ,
232- jpg : "image/jpeg" ,
233- jpeg : "image/jpeg" ,
234- png : "image/png" ,
235- gif : "image/gif" ,
236- svg : "image/svg+xml" ,
237- } ;
238- mimeType = mimeTypes [ ext || "" ] || "application/octet-stream" ;
239- }
216+ // v7.2 action:"query" returns stubs with only id/endpoint/parentReference.
217+ // Enrich each item by fetching full metadata from the Graph API.
218+ const enrichItems = async ( ) => {
219+ const enriched = await Promise . all (
220+ response . value . map ( async ( item : any ) => {
221+ const driveId =
222+ item . parentReference ?. driveId || item . id ?. split ( "!" ) [ 0 ] ;
223+ const itemId = item . id ;
240224
241- return {
242- id : item . id ,
243- name : item . name || `${ this . getProviderName ( ) } File` ,
244- mimeType : mimeType || "application/octet-stream" ,
245- webUrl : item . webUrl || "" ,
246- downloadUrl : item [ "@microsoft.graph.downloadUrl" ] || "" ,
247- size : item . size ,
248- modifiedTime : item . lastModifiedDateTime ,
249- isFolder : ! ! item . folder ,
250- } ;
251- } ) || [ ] ;
225+ if ( driveId && itemId ) {
226+ try {
227+ const url = `https://graph.microsoft.com/v1.0/drives/${ driveId } /items/${ itemId } ` ;
228+ const res = await fetch ( url , {
229+ headers : { Authorization : `Bearer ${ this . accessToken } ` } ,
230+ } ) ;
231+ if ( res . ok ) {
232+ const meta = await res . json ( ) ;
233+ console . log (
234+ "OneDrive enriched metadata:" ,
235+ meta . name ,
236+ meta . file ?. mimeType ,
237+ ) ;
238+
239+ let mimeType = meta . file ?. mimeType ;
240+ if ( ! mimeType && meta . name ) {
241+ const ext = meta . name . split ( "." ) . pop ( ) ?. toLowerCase ( ) ;
242+ const mimeTypes : { [ key : string ] : string } = {
243+ pdf : "application/pdf" ,
244+ doc : "application/msword" ,
245+ docx : "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ,
246+ xls : "application/vnd.ms-excel" ,
247+ xlsx : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ,
248+ ppt : "application/vnd.ms-powerpoint" ,
249+ pptx : "application/vnd.openxmlformats-officedocument.presentationml.presentation" ,
250+ txt : "text/plain" ,
251+ csv : "text/csv" ,
252+ json : "application/json" ,
253+ xml : "application/xml" ,
254+ html : "text/html" ,
255+ jpg : "image/jpeg" ,
256+ jpeg : "image/jpeg" ,
257+ png : "image/png" ,
258+ gif : "image/gif" ,
259+ svg : "image/svg+xml" ,
260+ } ;
261+ mimeType =
262+ mimeTypes [ ext || "" ] || "application/octet-stream" ;
263+ }
252264
253- onFileSelected ( newFiles ) ;
265+ return {
266+ id : meta . id ,
267+ name : meta . name || `${ this . getProviderName ( ) } File` ,
268+ mimeType : mimeType || "application/octet-stream" ,
269+ webUrl : meta . webUrl || "" ,
270+ downloadUrl : meta [ "@microsoft.graph.downloadUrl" ] || "" ,
271+ size : meta . size ,
272+ modifiedTime : meta . lastModifiedDateTime ,
273+ isFolder : ! ! meta . folder ,
274+ } as CloudFile ;
275+ } else {
276+ console . warn (
277+ "Graph API metadata fetch failed:" ,
278+ res . status ,
279+ await res . text ( ) ,
280+ ) ;
281+ }
282+ } catch ( e ) {
283+ console . warn ( "Graph API metadata fetch error:" , e ) ;
284+ }
285+ }
286+
287+ // Fallback: use stub data if Graph call fails
288+ return {
289+ id : item . id ,
290+ name : item . name || `${ this . getProviderName ( ) } File` ,
291+ mimeType : "application/octet-stream" ,
292+ webUrl : item . webUrl || "" ,
293+ downloadUrl : item [ "@microsoft.graph.downloadUrl" ] || "" ,
294+ size : item . size ,
295+ modifiedTime : item . lastModifiedDateTime ,
296+ isFolder : ! ! item . folder ,
297+ } as CloudFile ;
298+ } ) ,
299+ ) ;
300+
301+ onFileSelected ( enriched ) ;
302+ this . onPickerStateChange ?.( false ) ;
303+ } ;
304+
305+ enrichItems ( ) . catch ( ( e ) => {
306+ console . error ( "Failed to enrich OneDrive items:" , e ) ;
307+ this . onPickerStateChange ?.( false ) ;
308+ } ) ;
254309 } ,
255310 cancel : ( ) => {
256311 console . log ( "Picker cancelled" ) ;
312+ this . onPickerStateChange ?.( false ) ;
257313 } ,
258314 error : ( error : any ) => {
259315 console . error ( "Picker error callback:" , error ) ;
316+ this . onPickerStateChange ?.( false ) ;
260317 } ,
261318 } ) ;
262319 }
@@ -310,7 +367,13 @@ export const createProviderHandler = (
310367 if ( ! clientId ) {
311368 throw new Error ( "Client ID required for OneDrive" ) ;
312369 }
313- return new OneDriveHandler ( accessToken , clientId , provider , baseUrl ) ;
370+ return new OneDriveHandler (
371+ accessToken ,
372+ clientId ,
373+ provider ,
374+ baseUrl ,
375+ onPickerStateChange ,
376+ ) ;
314377 default :
315378 throw new Error ( `Unsupported provider: ${ provider } ` ) ;
316379 }
0 commit comments