Skip to content

Commit

Permalink
Merge pull request #17 from GustavoASC/copy-url
Browse files Browse the repository at this point in the history
Developed command to copy URL to clipboard
  • Loading branch information
GustavoASC authored Feb 27, 2021
2 parents 7636d0d + 7ead605 commit c4a56a7
Show file tree
Hide file tree
Showing 13 changed files with 205 additions and 7 deletions.
16 changes: 11 additions & 5 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,19 @@
"type": "node",
"request": "launch",
"name": "Mocha Tests",
"program": "${workspaceRoot}/node_modules/mocha/bin/mocha",
"program": "${workspaceFolder}/node_modules/mocha/bin/mocha",
"args": [
"--inspect-brk",
"${workspaceFolder}/out/test/**/*.js"
"--reporter",
"dot",
"--slow",
"5000",
"--colors",
"${workspaceFolder}/out/test/drive/**/*.js",
],
"port": 9229,
"internalConsoleOptions": "openOnSessionStart"
"internalConsoleOptions": "openOnSessionStart",
"skipFiles": [
"<node_internals>/**"
]
}
]
}
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).

## [1.2.0] - 2021-02-25
### Added

- Developed command to copy file or folder URL to clipboard.

## [1.1.1] - 2020-11-18
### Fixed

Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ You can preview file content directly from VSCode using your favorite theme. Thi
and you are able to take a look at the file in a fast way.

!['File preview' File preview](img/gif/preview.gif)

### Copy URL to clipboard
In case you prefer to view the file or folder content in the web browser itself, you can copy the URL to the clipboard through the context menu.

!['Copying URL' Copying URL](img/gif/copy-url.gif)

### Navigation
Feel free to navigate through your remote files and folders in a tree structure, which is available on the *Google Drive™* View located on the Side Bar.
Expand Down Expand Up @@ -65,7 +70,7 @@ In order to use this extension you need to set up Google Drive™ API on your Go
Once you have *credentials.json* file, access Command Palette on VSCode and run the command: *Google Drive: Configure credentials*, and select the *credentials.json* file.

## Known issues
* On versions smaller than v1.48 (Insiders), the file preview does not properly preview binary data e.g. image files. v1.48 will soon be the minimum version to run this extension.
* On versions smaller than v1.48, the file preview does not properly preview binary data e.g. image files. v1.48 will soon be the minimum version to run this extension.

## Trademark
Google Drive is a trademark of Google Inc. Use of this trademark is subject to Google Permissions.
Binary file added img/gif/copy-url.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"license": "MIT",
"publisher": "GustavoASC",
"version": "1.1.1",
"version": "1.2.0",
"icon": "img/icon.png",
"engines": {
"vscode": "^1.43.0"
Expand Down Expand Up @@ -81,6 +81,10 @@
"title": "Google Drive: Rename file on Drive",
"icon": "$(edit)"
},
{
"command": "google.drive.copyurl",
"title": "Google Drive: Copy URL to clipboard"
},
{
"command": "google.drive.openFile",
"title": "Google Drive: Preview selected file",
Expand Down Expand Up @@ -145,6 +149,10 @@
"command": "google.drive.rename",
"when": "view == driveView"
},
{
"command": "google.drive.copyurl",
"when": "view == driveView"
},
{
"command": "google.drive.openFile",
"when": "view == driveView",
Expand Down
21 changes: 21 additions & 0 deletions src/drive/controller/CopyToClipboardSupport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { DriveModel } from "../model/driveModel";
import { IDriveView } from "../view/driveView";
import { IControllerSupport } from "./controllerSupport";
import { DriveUrlBuilder } from "../model/driveUrlBuilder";
import { IClipboardProvider } from "./clipboardProvider";

export class CopyToClipboardSupport implements IControllerSupport {

private builder = new DriveUrlBuilder();

constructor(private provider: IClipboardProvider) {};

fireCommand(model: DriveModel, view: IDriveView, fileId: string): void {
const url = this.builder.buildUrlFromId(model, fileId);
if (url) {
this.provider.writeToClipboard(url);
view.showInformationMessage('Remote URL copied to clipboard.')
}
}

}
6 changes: 6 additions & 0 deletions src/drive/controller/clipboardProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

export interface IClipboardProvider {

writeToClipboard(text: string): void;

}
7 changes: 7 additions & 0 deletions src/drive/controller/driveController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { OpenRemoteFileSupport } from "./openRemoteFileSupport";
import { IControllerSupport } from "./controllerSupport";
import { DRIVE_SCHEME } from "../fileSystem/fileSystemConstants";
import { UploadFolderSupport } from "./uploadFolderSupport";
import { CopyToClipboardSupport } from "./CopyToClipboardSupport";
import { IClipboardProvider } from "./clipboardProvider";

export class DriveController {

Expand Down Expand Up @@ -70,6 +72,11 @@ export class DriveController {
this.fireCommand(this.renameSupport, fileId);
}

copyUrlToClipboard(clipboardProvider: IClipboardProvider, fileId: string): void {
const copyToClipboardSupport = new CopyToClipboardSupport(clipboardProvider);
this.fireCommand(copyToClipboardSupport, fileId);
}

openRemoteFile(fileId: string): void {
this.fireCommand(this.openSupport, fileId);
}
Expand Down
28 changes: 28 additions & 0 deletions src/drive/model/driveUrlBuilder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { DriveModel } from "./driveModel";
import { DriveFile, FileType } from "./driveTypes";

const DRIVE_WEBSITE = 'https://drive.google.com';

export class DriveUrlBuilder {

buildUrlFromId(model: DriveModel, fileId: string): string | undefined {
const file = model.getDriveFile(fileId);
if (file) {
return this.buildUrlFromFile(file);
}
return undefined;
}

private buildUrlFromFile(file: DriveFile): string {
const location = this.getFileTypeLocation(file.type);
const finalUrl = DRIVE_WEBSITE + location + file.id;
return finalUrl;
}

private getFileTypeLocation(type: FileType): string {
return type == FileType.DIRECTORY
? '/drive/folders/'
: '/file/d/';
}

}
12 changes: 12 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { DriveFileSystemProvider } from './drive/fileSystem/driveFileSystemProvi
import { DRIVE_SCHEME } from './drive/fileSystem/fileSystemConstants';
import { DriveView } from './drive/view/driveView';
import { CredentialsManager } from './drive/credentials/credentialsManager';
import { VscodeClipboardProvider } from './vscodeClipboardProvider';

export const CONFIGURE_CREDENTIALS_COMMAND = 'google.drive.configureCredentials';
export const CREATE_FOLDER_COMMAND = 'google.drive.createFolder';
Expand Down Expand Up @@ -55,6 +56,9 @@ export function activate({ subscriptions }: vscode.ExtensionContext) {
subscriptions.push(vscode.commands.registerCommand('google.drive.rename', (selectedFileId: any) => {
renameSelectedFile(selectedFileId, controller);
}));
subscriptions.push(vscode.commands.registerCommand('google.drive.copyurl', (selectedFileId: any) => {
copyUrlToClipboard(selectedFileId, controller);
}));
subscriptions.push(vscode.commands.registerCommand('google.drive.openFile', (selectedFileId: any) => {
openRemoteFile(selectedFileId, controller);
}));
Expand Down Expand Up @@ -115,6 +119,14 @@ function renameSelectedFile(selectedFileId: any, controller: DriveController): v
}
}

function copyUrlToClipboard(selectedFileId: any, controller: DriveController): void {
if (selectedFileId) {
controller.copyUrlToClipboard(new VscodeClipboardProvider(), selectedFileId);
} else {
vscode.window.showWarningMessage('This command can only be directly used from Google Drive view.');
}
}

function openRemoteFile(selectedFileId: any, controller: DriveController): void {
if (selectedFileId) {
controller.openRemoteFile(selectedFileId);
Expand Down
57 changes: 57 additions & 0 deletions src/test/drive/controller/driveController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { DriveController } from '../../../drive/controller/driveController';
import { EmptyMockFileProvider } from '../model/abstractFileProvider.test';
import { DRIVE_SCHEME } from '../../../drive/fileSystem/fileSystemConstants';
import { AbstractDriveView } from '../view/abstractDriveView.test';
import { IClipboardProvider } from '../../../drive/controller/clipboardProvider';
import { DriveFile, FileType } from '../../../drive/model/driveTypes';
import { AbstractMockFileProvider } from '../model/abstractFileProvider.test';

describe('Drive controller operations', () => {

Expand All @@ -23,8 +26,62 @@ describe('Drive controller operations', () => {
controller.uploadFileAndAskFolder('file://', './extension.ts');
});

it('Copies URL to clipboard', async () => {
const model = new DriveModel(new MockFileProvider());
await model.listFiles('root');
const view = new UrlCopiedView();
const controller = new DriveController(model, view);
const clipboardProvider = new DummyClipboardProvider();
view.viewMessage = '';
controller.copyUrlToClipboard(clipboardProvider, '1Cdffsdfsdfsdfdfocz');
expect('Remote URL copied to clipboard.').to.equal(view.viewMessage);
expect('https://drive.google.com/file/d/1Cdffsdfsdfsdfdfocz').to.equal(clipboardProvider.clipboard);
view.viewMessage = '';
controller.copyUrlToClipboard(clipboardProvider, '1C7udIKXCkxsvXO37gCBpfaasqn9wocz');
expect('Remote URL copied to clipboard.').to.equal(view.viewMessage);
expect('https://drive.google.com/drive/folders/1C7udIKXCkxsvXO37gCBpfaasqn9wocz').to.equal(clipboardProvider.clipboard);
});

});

class UrlCopiedView extends AbstractDriveView {

viewMessage : string = "";

showInformationMessage(message: string, ...items: string[]): Thenable<string | undefined> {
return new Promise((resolve, reject) => {
this.viewMessage = message;
resolve('test');
});
}

}

class DummyClipboardProvider implements IClipboardProvider {

clipboard: string = "";

writeToClipboard(text: string): void {
this.clipboard = text;
}

}

class MockFileProvider extends AbstractMockFileProvider {

provideFiles(parentFolderId: string): Promise<DriveFile[]> {
return new Promise((resolve) => {
const firstFolder: DriveFile = { iconLink: 'http://www.mylink.com/folder', id: '1C7udIKXadsdssdsadsadsddsocz', name: 'VSCode', type: FileType.DIRECTORY, size: 0, createdTime: 1341393000000, modifiedTime: 1341393000000 };
const secondFolder: DriveFile = { iconLink: 'http://www.mylink.com/folder', id: '1C7udIKXCkxsvXO37gvfbfbdfbHihn9wocz', name: 'subFolder', type: FileType.DIRECTORY, parent: firstFolder, size: 0, createdTime: 1341393000000, modifiedTime: 1341393000000 };
const thirdFolder: DriveFile = { iconLink: 'http://www.mylink.com/folder', id: '1C7udIKXCkxsvXO37gCBpfaasqn9wocz', name: 'thirdFolder', type: FileType.DIRECTORY, parent: secondFolder, size: 0, createdTime: 1341393000000, modifiedTime: 1341393000000 };
const finalFile: DriveFile = { iconLink: 'http://www.mylink.com/file', id: '1Cdffsdfsdfsdfdfocz', name: 'myFile.txt', type: FileType.FILE, parent: secondFolder, size: 1325, createdTime: 1341393000000, modifiedTime: 1341393000000 };
resolve([thirdFolder, finalFile]);
});
}

}


class WrongSchemeDriveView extends AbstractDriveView {

warningShown = false;
Expand Down
33 changes: 33 additions & 0 deletions src/test/drive/model/driveUrlBuilder.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { expect } from 'chai';
import 'mocha';
import { DriveModel } from '../../../drive/model/driveModel';
import { DriveFile, FileType } from '../../../drive/model/driveTypes';
import { AbstractMockFileProvider } from './abstractFileProvider.test';
import { DriveUrlBuilder } from '../../../drive/model/driveUrlBuilder';

describe('Remote URL manipulation', () => {

it('Checks remote URL building', async () => {
const model = new DriveModel(new MockFileProvider());
await model.listFiles('root');
const urlBuilder = new DriveUrlBuilder();
expect('https://drive.google.com/file/d/1Cdffsdfsdfsdfdfocz').to.equal(urlBuilder.buildUrlFromId(model, '1Cdffsdfsdfsdfdfocz'));
expect('https://drive.google.com/drive/folders/1C7udIKXCkxsvXO37gCBpfaasqn9wocz').to.equal(urlBuilder.buildUrlFromId(model, '1C7udIKXCkxsvXO37gCBpfaasqn9wocz'));
expect(undefined).to.equal(urlBuilder.buildUrlFromId(model, 'xxxxxx'));
});

});

class MockFileProvider extends AbstractMockFileProvider {

provideFiles(parentFolderId: string): Promise<DriveFile[]> {
return new Promise((resolve) => {
const firstFolder: DriveFile = { iconLink: 'http://www.mylink.com/folder', id: '1C7udIKXadsdssdsadsadsddsocz', name: 'VSCode', type: FileType.DIRECTORY, size: 0, createdTime: 1341393000000, modifiedTime: 1341393000000 };
const secondFolder: DriveFile = { iconLink: 'http://www.mylink.com/folder', id: '1C7udIKXCkxsvXO37gvfbfbdfbHihn9wocz', name: 'subFolder', type: FileType.DIRECTORY, parent: firstFolder, size: 0, createdTime: 1341393000000, modifiedTime: 1341393000000 };
const thirdFolder: DriveFile = { iconLink: 'http://www.mylink.com/folder', id: '1C7udIKXCkxsvXO37gCBpfaasqn9wocz', name: 'thirdFolder', type: FileType.DIRECTORY, parent: secondFolder, size: 0, createdTime: 1341393000000, modifiedTime: 1341393000000 };
const finalFile: DriveFile = { iconLink: 'http://www.mylink.com/file', id: '1Cdffsdfsdfsdfdfocz', name: 'myFile.txt', type: FileType.FILE, parent: secondFolder, size: 1325, createdTime: 1341393000000, modifiedTime: 1341393000000 };
resolve([thirdFolder, finalFile]);
});
}

}
10 changes: 10 additions & 0 deletions src/vscodeClipboardProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { IClipboardProvider } from "./drive/controller/clipboardProvider";
import * as vscode from 'vscode';

export class VscodeClipboardProvider implements IClipboardProvider {

writeToClipboard(text: string): void {
vscode.env.clipboard.writeText(text)
}

}

0 comments on commit c4a56a7

Please sign in to comment.