mirror of
				https://github.com/arduino/arduino-ide.git
				synced 2025-10-30 21:48:33 +00:00 
			
		
		
		
	 1ae60ec9bc
			
		
	
	1ae60ec9bc
	
	
	
		
			
			Co-authored-by: Mark Sujew <mark.sujew@typefox.io> Co-authored-by: Akos Kitta <a.kitta@arduino.cc> Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
		
			
				
	
	
		
			161 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { inject, injectable } from '@theia/core/shared/inversify';
 | |
| import { URI as Uri } from 'vscode-uri';
 | |
| import URI from '@theia/core/lib/common/uri';
 | |
| import { Deferred } from '@theia/core/lib/common/promise-util';
 | |
| import {
 | |
|   FileSystemProvider,
 | |
|   FileSystemProviderError,
 | |
|   FileSystemProviderErrorCode,
 | |
| } from '@theia/filesystem/lib/common/files';
 | |
| import { DisposableCollection } from '@theia/core/lib/common/disposable';
 | |
| import { DelegatingFileSystemProvider } from '@theia/filesystem/lib/common/delegating-file-system-provider';
 | |
| import {
 | |
|   FileService,
 | |
|   FileServiceContribution,
 | |
| } from '@theia/filesystem/lib/browser/file-service';
 | |
| import { AuthenticationClientService } from '../auth/authentication-client-service';
 | |
| import { AuthenticationSession } from '../../common/protocol/authentication-service';
 | |
| import { ConfigService } from '../../common/protocol';
 | |
| 
 | |
| export namespace LocalCacheUri {
 | |
|   export const scheme = 'arduino-local-cache';
 | |
|   export const root = new URI(
 | |
|     Uri.parse('/').with({ scheme, authority: 'create' })
 | |
|   );
 | |
| }
 | |
| 
 | |
| @injectable()
 | |
| export class LocalCacheFsProvider
 | |
|   implements FileServiceContribution, DelegatingFileSystemProvider.URIConverter
 | |
| {
 | |
|   @inject(ConfigService)
 | |
|   protected readonly configService: ConfigService;
 | |
| 
 | |
|   @inject(AuthenticationClientService)
 | |
|   protected readonly authenticationService: AuthenticationClientService;
 | |
| 
 | |
|   // TODO: do we need this? Cannot we `await` on the `init` call from `registerFileSystemProviders`?
 | |
|   readonly ready = new Deferred<void>();
 | |
| 
 | |
|   private _localCacheRoot: URI;
 | |
| 
 | |
|   registerFileSystemProviders(fileService: FileService): void {
 | |
|     fileService.onWillActivateFileSystemProvider(async (event) => {
 | |
|       if (event.scheme === LocalCacheUri.scheme) {
 | |
|         event.waitUntil(
 | |
|           (async () => {
 | |
|             this.init(fileService);
 | |
|             const provider = await this.createProvider(fileService);
 | |
|             fileService.registerProvider(LocalCacheUri.scheme, provider);
 | |
|           })()
 | |
|         );
 | |
|       }
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   to(resource: URI): URI | undefined {
 | |
|     const relativePath = LocalCacheUri.root.relative(resource);
 | |
|     if (relativePath) {
 | |
|       return this.currentUserUri.resolve(relativePath).normalizePath();
 | |
|     }
 | |
|     return undefined;
 | |
|   }
 | |
| 
 | |
|   from(resource: URI): URI | undefined {
 | |
|     const relativePath = this.currentUserUri.relative(resource);
 | |
|     if (relativePath) {
 | |
|       return LocalCacheUri.root.resolve(relativePath);
 | |
|     }
 | |
|     return undefined;
 | |
|   }
 | |
| 
 | |
|   protected async createProvider(
 | |
|     fileService: FileService
 | |
|   ): Promise<FileSystemProvider> {
 | |
|     const delegate = await fileService.activateProvider('file');
 | |
|     await this.ready.promise;
 | |
|     return new DelegatingFileSystemProvider(
 | |
|       delegate,
 | |
|       {
 | |
|         uriConverter: this,
 | |
|       },
 | |
|       new DisposableCollection(
 | |
|         delegate.watch(this.localCacheRoot, {
 | |
|           excludes: [],
 | |
|           recursive: true,
 | |
|         })
 | |
|       )
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   protected async init(fileService: FileService): Promise<void> {
 | |
|     const config = await this.configService.getConfiguration();
 | |
|     this._localCacheRoot = new URI(config.dataDirUri);
 | |
|     for (const segment of ['RemoteSketchbook', 'ArduinoCloud']) {
 | |
|       this._localCacheRoot = this._localCacheRoot.resolve(segment);
 | |
|       await fileService.createFolder(this._localCacheRoot);
 | |
|     }
 | |
|     this.session(fileService).then(() => this.ready.resolve());
 | |
|     this.authenticationService.onSessionDidChange(async (session) => {
 | |
|       if (session) {
 | |
|         await this.ensureExists(session, fileService);
 | |
|       }
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   public get currentUserUri(): URI {
 | |
|     const { session } = this.authenticationService;
 | |
|     if (!session) {
 | |
|       throw new FileSystemProviderError(
 | |
|         'Not logged in.',
 | |
|         FileSystemProviderErrorCode.NoPermissions
 | |
|       );
 | |
|     }
 | |
|     return this.toUri(session);
 | |
|   }
 | |
| 
 | |
|   private get localCacheRoot(): URI {
 | |
|     return this._localCacheRoot;
 | |
|   }
 | |
| 
 | |
|   private async session(
 | |
|     fileService: FileService
 | |
|   ): Promise<AuthenticationSession> {
 | |
|     return new Promise<AuthenticationSession>(async (resolve) => {
 | |
|       const { session } = this.authenticationService;
 | |
|       if (session) {
 | |
|         await this.ensureExists(session, fileService);
 | |
|         resolve(session);
 | |
|         return;
 | |
|       }
 | |
|       const toDispose = new DisposableCollection();
 | |
|       toDispose.push(
 | |
|         this.authenticationService.onSessionDidChange(async (session) => {
 | |
|           if (session) {
 | |
|             await this.ensureExists(session, fileService);
 | |
|             toDispose.dispose();
 | |
|             resolve(session);
 | |
|           }
 | |
|         })
 | |
|       );
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   private async ensureExists(
 | |
|     session: AuthenticationSession,
 | |
|     fileService: FileService
 | |
|   ): Promise<URI> {
 | |
|     const uri = this.toUri(session);
 | |
|     const exists = await fileService.exists(uri);
 | |
|     if (!exists) {
 | |
|       await fileService.createFolder(uri);
 | |
|     }
 | |
|     return uri;
 | |
|   }
 | |
| 
 | |
|   private toUri(session: AuthenticationSession): URI {
 | |
|     // Hack: instead of getting the UUID only, we get `auth0|UUID` after the authentication. `|` cannot be part of filesystem path or filename.
 | |
|     return this._localCacheRoot.resolve(session.id.split('|')[1]);
 | |
|   }
 | |
| }
 |