From 00dfd46efd4c2a7898c957c6c0539a792e32f7f7 Mon Sep 17 00:00:00 2001 From: Nilesh Date: Fri, 19 Apr 2019 19:19:48 +0530 Subject: [PATCH 01/64] Updated to task api 2.0.0 and fixed tests --- .vscode/launch.json | 4 ++-- .vscode/tasks.json | 54 ++++++++++++++++++++++----------------------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 35677aff..29e14514 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "stopOnEntry": false, "sourceMaps": true, "outFiles": ["${workspaceRoot}/out/**/*.js"], - "preLaunchTask": "npm" + "preLaunchTask": "build" }, { "name": "Launch Tests", @@ -21,7 +21,7 @@ "stopOnEntry": false, "sourceMaps": true, "outFiles": ["${workspaceRoot}/out/test/**/*.js"], - "preLaunchTask": "npm" + "preLaunchTask": "test_build" } ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d31b1591..6d58de27 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,30 +1,28 @@ -// Available variables which can be used inside of strings. -// ${workspaceRoot}: the root folder of the team -// ${file}: the current opened file -// ${fileBasename}: the current opened file's basename -// ${fileDirname}: the current opened file's dirname -// ${fileExtname}: the current opened file's extension -// ${cwd}: the current working directory of the spawned process - -// A task runner that calls a custom npm script that compiles the extension. { - "version": "0.1.0", - - // we want to run npm - "command": "npm", - - // the command is a shell script - "isShellCommand": true, - - // show the output window only if unrecognized errors occur. - "showOutput": "silent", - - // we run the custom script "compile" as defined in package.json - "args": ["run", "compile", "--loglevel", "silent"], - - // The tsc compiler is started in watching mode - "isWatching": true, - - // use the standard tsc in watch mode problem matcher to find compile problems in the output. - "problemMatcher": "$tsc-watch" + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "command": "npm", + "args": [ + "run", + "compile", + "--loglevel", + "silent" + ], + "problemMatcher": "$tsc-watch" + }, + { + "label": "test_build", + "type": "shell", + "command": "tsc", + "args": [ + "-p", + "./" + ] + } + ] } \ No newline at end of file From 4e1d08d61baa022f7d4f28fa17b3f0db6a4ffd39 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 2 May 2019 15:41:44 -0700 Subject: [PATCH 02/64] Set "extensionKind": "ui" to support remote development #61 Fixes #870. See that issue for details --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index c98e5c1f..e99e4b82 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "workspace-sync", "multi-root ready" ], + "extensionKind": "ui", "activationEvents": [ "*" ], From 774bccef1b2c23bc7beca6827b99b8484cc17727 Mon Sep 17 00:00:00 2001 From: Arno Hovhannisyan Date: Sat, 4 May 2019 16:39:59 -0700 Subject: [PATCH 03/64] Clean up previous commits into one --- README.md | 134 ++++------- package.json | 11 +- package.nls.ja.json | 1 + package.nls.json | 6 +- package.nls.zh-cn.json | 1 + release-notes.json | 40 ++++ src/commons.ts | 317 ++++++++++++++++++++------ src/models/settingType.model.ts | 5 + src/service/oauthService.ts | 114 +++++++++ src/sync.ts | 41 ++-- ui/gist-selection/gist-selection.html | 69 ++++++ ui/gist-selection/gist-selection.js | 60 +++++ ui/landing-page/landing-page.html | 160 +++++++++++++ ui/landing-page/landing-page.js | 33 +++ ui/settings/settings.html | 89 ++++++++ ui/settings/settings.js | 187 +++++++++++++++ ui/shared/page-header.js | 19 ++ ui/shared/styles.css | 129 +++++++++++ 18 files changed, 1232 insertions(+), 184 deletions(-) create mode 100644 release-notes.json create mode 100644 src/models/settingType.model.ts create mode 100644 src/service/oauthService.ts create mode 100644 ui/gist-selection/gist-selection.html create mode 100644 ui/gist-selection/gist-selection.js create mode 100644 ui/landing-page/landing-page.html create mode 100644 ui/landing-page/landing-page.js create mode 100644 ui/settings/settings.html create mode 100644 ui/settings/settings.js create mode 100644 ui/shared/page-header.js create mode 100644 ui/shared/styles.css diff --git a/README.md b/README.md index 54686c14..d2176ba8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,5 @@ # Settings Sync [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Synchronize%20your%20%40VisualStudio%20%40code%20Settings%20Across%20Multiple%20Machines%20using%20%40github%20GIST%20by%20%40itsShanKhan&url=https://github.com/shanalikhan/code-settings-sync&via=code&hashtags=code,vscode,SettingsSync,developers) [![Follow](https://img.shields.io/twitter/follow/itsShanKhan.svg?style=social&label=Follow)](https://twitter.com/intent/follow?screen_name=itsShanKhan) - - - **Previously known as Visual Studio Code Settings Sync** [![Version](https://vsmarketplacebadge.apphb.com/version/Shan.code-settings-sync.svg)](https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync) [![Travis](https://img.shields.io/travis/rust-lang/rust.svg)](https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync) @@ -11,7 +8,7 @@ ## Support -While being free and open source, if you find it useful, please consider supporting it by donating via PayPal or Open Collective. If you are using it in office as a team, please ask your company to support us via Open Collective from just 2$ per month! +While being free and open source, if you find it useful, please consider supporting it by donating via PayPal or Open Collective. If you are using it in office as a team, please ask your company to support us via Open Collective from just 2\$ per month! @@ -42,7 +39,7 @@ While being free and open source, if you find it useful, please consider support ## Key Features -``` +``` 1. Use your GitHub account token and Gist. 2. Easy to Upload and Download on one click. 3. Show a summary page at the end with details about config and extensions effected. @@ -51,10 +48,11 @@ While being free and open source, if you find it useful, please consider support 6. Share the Gist with other users and let them download your settings. 7. Supports GitHub Enterprise 8. Support pragmas with @sync keywords: host, os and env are supported. +9. GUI for changing settings / logging in ``` - ## It Syncs + ``` All extensions and complete User Folder that Contains 1. Settings File @@ -66,85 +64,41 @@ All extensions and complete User Folder that Contains ``` ## Shortcuts + ``` 1. Upload Key : Shift + Alt + U 2. Download Key : Shift + Alt + D ``` -## Steps To Get a Personal Access Token from GitHub - -This extension requires a Personal Access Token from your GitHub account. You can create one by simply following the steps shown in the pictures below. Make sure you add **Gist** in scope. - -**[Generate New Token](https://github.com/settings/tokens/new?description=code-setting-sync&scopes=gist)** - -![Select Scopes](https://shanalikhan.github.io/img/github2.PNG) - -**Get an Access Token.** - -![Get Access Token](https://shanalikhan.github.io/img/github3.PNG) - - -> Save the Token somewhere for future use (i.e. to upload from other machines). - - ## Upload Your Settings For the first time **Press Shift + Alt + U it will ask your GitHub account access token.** > Type ">Sync" In Command Palette into order download / upload -This will automatically open your GitHub settings page, allowing you to generate a new token for the application, as explained in the previous section. This token will allow the extension to create gists. - -Enter the GitHub token in the window and click enter. - -![github account access token](https://shanalikhan.github.io/img/upload1.png) - -**Upload your settings automatically and the extension gives you Gist ID in the system message.** -Gist ID is needed to access the data you have uploaded with your token. Copy this Gist ID in order to download the settings to other machines. - -![uploaded automatically](https://shanalikhan.github.io/img/upload2.png) +When downloading or uploading for the first time, the welcome page will automatically open, where you can log in with GitHub. -You can always **verify created gist** on the following url: +![Login with GitHub](https://user-images.githubusercontent.com/25834068/55663873-93c21280-57d9-11e9-8c24-7088a81ed47c.png) -> https://gist.github.com/{your_userName}/{gist_id} - -Here is the gif of the complete process when you execute the Upload command (Might take some time to load) - -![Upload](https://media.giphy.com/media/xT9IglKxSqs2Wdwq2c/source.gif) +You can always **verify created gist** by going to `https://gist.github.com` and checking for a gist named `cloudSettings` ## Download your Settings -**Press Shift + Alt + D it will ask your GitHub Gist ID.** - > Type ">Sync" In Command Palette into order download / upload -**Enter Your GitHub Token.** - -Enter the GitHub token in the window and click enter. - -![github account access token](https://shanalikhan.github.io/img/upload1.png) +**Login with GitHub** -**Enter Your Gist ID.** +**Choose your existing Gist** -You need to enter your Gist ID in order to download the files you have uploaded with Shift + Alt + U. - -![Enter Your Gist ID](https://shanalikhan.github.io/img/download2.png) +![Existing Gist](https://user-images.githubusercontent.com/25834068/55663880-a9373c80-57d9-11e9-8afc-c0e79cc1b3b5.png) **Settings Downloaded.** -You are Done! All your files are downloaded - -![Enter Your Gist ID](https://shanalikhan.github.io/img/download3.png) - -Here is the gif of the complete process when you execute the Download command (Might take time to load) - - -![Download](https://media.giphy.com/media/xT9Iglsi3CS9noE8tW/source.gif) +You are Done! All your files are downloaded ## Reset Extension Settings -> Type ">Sync" In Command Palette and select Reset Extension Settings - +> Select **"> Sync : Reset Extension Settings"** in the Command Palette to reset your settings ## Toggle Auto Download @@ -169,7 +123,6 @@ Please make sure you have valid github Token and Gist available to make it work Select Command **"Sync : Advanced Options > Toggle Auto-Upload on Settings Change"** command to Turn ON / OFF the auto-upload. - ## Toggle Summary Summary is **enabled by default** which shows all files and extensions that are added or deleted on a single page. @@ -186,9 +139,10 @@ Select Command **"Sync : Advanced Options > Share Settings with Public GIST"** Other users can give your Gist Id to download the Gist, but they can't upload their settings on your Gist. - ## Settings +Settings can be changed through the settings page, which can be accessed through **"> Sync : Advanced Options > Open Settings Page"** + There are two types of settings in Settings Sync. I will recommend you to read the configurations details [here](https://medium.com/@itsShanKhan/visual-studio-code-settings-sync-configurations-ed8dd6fd9753). @@ -199,7 +153,7 @@ You can customize the settings in gist settings like: ``` 1. Configure Gist Id (Environment) -2. Configure auto upload / download for Github Gist +2. Configure auto upload / download for Github Gist 3. Configure extension sync behaviour 4. Configure force download 5. Configure quiet sync @@ -211,7 +165,6 @@ You can customize the settings in gist settings like: "sync.autoUpload": false, "sync.forceDownload": false, "sync.quietSync": false, - "sync.askGistName": false, "sync.removeExtensions": true, "sync.syncExtensions": true ``` @@ -238,33 +191,30 @@ You can customize the sync: ```json { - "ignoreUploadFiles": [ - "projects.json", - "projects_cache_vscode.json", - "projects_cache_git.json", - "projects_cache_svn.json", - "gpm_projects.json", - "gpm-recentItems.json" - ], - "ignoreUploadFolders": [ - "workspaceStorage" - ], - "ignoreExtensions": [ - "ignored_extension_name" - ], - "gistDescription": "Visual Studio Code Settings Sync Gist", - "version": 310, - "token": "YOUR_GITHUB_TOKEN_HERE", - "downloadPublicGist": false, - "supportedFileExtensions": [ - "json", - "code-snippets" - ], - "openTokenLink": true, - "lastUpload": null, - "lastDownload": null, - "githubEnterpriseUrl": null, - "hostName": null + "ignoreUploadFiles": [ + "state.*", + "syncLocalSettings.json", + ".DS_Store", + "sync.lock", + "projects.json", + "projects_cache_vscode.json", + "projects_cache_git.json", + "projects_cache_svn.json", + "gpm_projects.json", + "gpm-recentItems.json" + ], + "ignoreUploadFolders": ["workspaceStorage"], + "ignoreExtensions": ["ignored_extension_name"], + "gistDescription": "Visual Studio Code Settings Sync Gist", + "version": 310, + "token": "YOUR_GITHUB_TOKEN_HERE", + "downloadPublicGist": false, + "supportedFileExtensions": ["json", "code-snippets"], + "openTokenLink": true, + "lastUpload": null, + "lastDownload": null, + "githubEnterpriseUrl": null, + "hostName": null } ``` @@ -294,20 +244,18 @@ Thank you to all our backers! [[Become a backer](https://opencollective.com/code [](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=4W3EWHHBSYMM8&lc=IE&item_name=Code%20Settings%20Sync&item_number=visual%20studio%20code%20settings%20sync¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted) - ### Sponsors Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/code-settings-sync)) ## [Contributors](https://github.com/shanalikhan/code-settings-sync/graphs/contributors) + # [Release Notes](https://shanalikhan.github.io/2016/05/14/Visual-studio-code-sync-settings-release-notes.html) # License - [![Version](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/shanalikhan/code-settings-sync/blob/master/LICENSE) - [![Version](https://vsmarketplacebadge.apphb.com/version/Shan.code-settings-sync.svg)](https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync) [![Installs](https://vsmarketplacebadge.apphb.com/installs/Shan.code-settings-sync.svg)](https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync) diff --git a/package.json b/package.json index e99e4b82..dc2a6206 100644 --- a/package.json +++ b/package.json @@ -154,9 +154,12 @@ }, "devDependencies": { "@types/chai": "4.1.7", + "@types/express": "^4.16.1", "@types/fs-extra": "^5.0.5", + "@types/lodash": "^4.14.123", "@types/mocha": "^5.2.6", "@types/node": "^11.13.0", + "@types/node-fetch": "^2.3.3", "chai": "^4.2.0", "clean-webpack-plugin": "^2.0.1", "mocha": "^6.0.2", @@ -172,10 +175,16 @@ }, "dependencies": { "@octokit/rest": "^16.23.2", + "adm-zip": "^0.4.13", + "const": "^1.0.0", + "express": "^4.16.4", "fs-extra": "^7.0.1", "https-proxy-agent": "^2.2.1", "lockfile": "^1.0.4", + "lodash": "^4.17.11", + "node-fetch": "^2.5.0", "temp": "^0.9.0", - "vscode-chokidar": "^1.6.5" + "vscode-chokidar": "^1.6.5", + "webpack-node-externals": "^1.7.2" } } diff --git a/package.nls.ja.json b/package.nls.ja.json index 2a48f1d2..7b1ef934 100644 --- a/package.nls.ja.json +++ b/package.nls.ja.json @@ -35,6 +35,7 @@ "cmd.resetSettings.info.resetting": "Sync : 設定をリセット中です.", "cmd.resetSettings.info.settingClear": "Sync : 設定がクリアされました.", "cmd.otherOptions.title": "Sync : 詳細なオプション", + "cmd.otherOptions.openSettingsPage": "Sync : Open Settings [needs translation]", "cmd.otherOptions.editLocalSetting": "Sync : 拡張機能のローカル設定の編集", "cmd.otherOptions.shareSetting": "Sync : 公開 GIST で設定の共有", "cmd.otherOptions.shareSetting.beforeConfirm": "Sync : これにより, 現在の GIST が削除され, 新しく公開 GIST に設定がアップロードされます. 続行しますか?", diff --git a/package.nls.json b/package.nls.json index 4a88d4db..a2d99616 100644 --- a/package.nls.json +++ b/package.nls.json @@ -36,6 +36,7 @@ "cmd.resetSettings.info.resetting": "Sync : Resetting Your Settings.", "cmd.resetSettings.info.settingClear": "Sync : Settings Cleared.", "cmd.otherOptions.title": "Sync : Advanced Options", + "cmd.otherOptions.openSettingsPage": "Sync : Open Settings", "cmd.otherOptions.editLocalSetting": "Sync : Edit Extension Local Settings", "cmd.otherOptions.shareSetting": "Sync : Share Settings with Public GIST", "cmd.otherOptions.shareSetting.beforeConfirm": "Sync : This will remove current GIST and upload settings on new public GIST. Do you want to continue?", @@ -69,7 +70,7 @@ "cmd.otherOptions.quietSync.off": "Sync : Summary will be shown upon download / upload.", "cmd.otherOptions.warning.tokenNotRequire": "Sync : Settings Sync will not ask for GitHub Token from now on.", "cmd.otherOptions.error.toggleFail": "Sync : Unable to Toggle.", - "cmd.otherOptions.triggerReset" : "Sync : Do you want to reset the settings ?", + "cmd.otherOptions.triggerReset": "Sync : Do you want to reset the settings ?", "common.info.installed": "Sync : Settings created, thank you for installing!", "common.info.needHelp": "Sync : Need Help configuring this extension?", "common.info.excludeFile": "Sync : You can exclude any file / folder for upload and settings for download.", @@ -101,6 +102,5 @@ "common.prompt.enterGistId": "Enter Gist Id from previously uploaded settings. You can also set manually in code settings (sync.gist). Press [Enter] or [Esc] to cancel.", "common.prompt.enterGithubAccessToken": "You also manually add a token (User Folder / syncLocalSettings.json). Press [Enter] or [Esc] to cancel.", "common.prompt.restartCode": "Do you want to reload to apply extensions and configurations?", - "common.button.yes" :"Yes" - + "common.button.yes": "Yes" } diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index a020644f..1ed0239e 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -35,6 +35,7 @@ "cmd.resetSettings.info.resetting": "Sync : 正在重置你的设置", "cmd.resetSettings.info.settingClear": "Sync : 设置清除完毕", "cmd.otherOptions.title": "Sync : 高级选项", + "cmd.otherOptions.openSettingsPage": "Sync : Open Settings [needs translation]", "cmd.otherOptions.editLocalSetting": "Sync : 编辑本地扩展设置", "cmd.otherOptions.shareSetting": "Sync : 分享设置到公开的 Gist", "cmd.otherOptions.shareSetting.beforeConfirm": "Sync : 这将会删除当前的 Gist 设置然后重新上传到一个新的 Gist 上, 你确定继续吗 ?", diff --git a/release-notes.json b/release-notes.json new file mode 100644 index 00000000..190e26a8 --- /dev/null +++ b/release-notes.json @@ -0,0 +1,40 @@ +{ + "changes": [ + { + "details": "Fixed Code that kills Extension Host for MacOS", + "type": "FIX", + "color": "danger", + "author": "arnohovhannisyan", + "pullRequest": "834" + }, + { + "details": "Download From Public Gist not working", + "type": "FIX", + "color": "danger", + "author": "shanalikhan", + "pullRequest": "816" + }, + { + "details": "Auto Upload Fix", + "type": "FIX", + "color": "danger", + "author": "arnohovhannisyan", + "pullRequest": "835" + }, + { + "details": "Inserts some empty lines in the beginning of settings.json", + "type": "NEW", + "color": "success", + "author": "knyhle", + "pullRequest": "828" + }, + { + "details": "Update Documentation", + "type": "NEW", + "color": "success", + "author": "colinaaa", + "pullRequest": "845" + } + ], + "currentVersion": "v3.2.9" +} diff --git a/src/commons.ts b/src/commons.ts index 09031dca..a603a0d9 100644 --- a/src/commons.ts +++ b/src/commons.ts @@ -1,9 +1,13 @@ "use strict"; +import { readFileSync } from "fs"; +import { has, set } from "lodash"; import * as vscode from "vscode"; import { Environment } from "./environmentPath"; import localize from "./localize"; +import { UISettingType } from "./models/settingType.model"; import { AutoUploadService } from "./service/autoUploadService"; import { File, FileService } from "./service/fileService"; +import { GitHubOAuthService } from "./service/oauthService"; import { ExtensionInformation } from "./service/pluginService"; import { CustomSettings, ExtensionConfig, LocalConfig } from "./setting"; @@ -70,15 +74,254 @@ export default class Commons { } } + public SettingsView: string; + public LandingPageView: string; + public autoUploadService: AutoUploadService; public ERROR_MESSAGE: string = localize("common.error.message"); + private customizableSettings = [ + { + name: "Hostname (optional)", + placeholder: "Enter Hostname", + type: UISettingType.TextInput, + correspondingSetting: "hostName" + }, + { + name: "Ignored Files", + placeholder: "Enter one file per line", + type: UISettingType.TextArea, + correspondingSetting: "ignoreUploadFiles" + }, + { + name: "Ignored Folders", + placeholder: "Enter one folder per line", + type: UISettingType.TextArea, + correspondingSetting: "ignoreUploadFolders" + }, + { + name: "Ignored Extensions", + placeholder: "Enter one extension per line (full name)", + type: UISettingType.TextArea, + correspondingSetting: "ignoreExtensions" + }, + { + name: "Supported File Extensions", + placeholder: "Enter one file extension per line", + type: UISettingType.TextArea, + correspondingSetting: "supportedFileExtensions" + }, + { + name: "Access Token", + placeholder: "Enter Token", + type: UISettingType.TextInput, + correspondingSetting: "token" + }, + { + name: "Gist Description", + placeholder: "Enter Gist Description", + type: UISettingType.TextInput, + correspondingSetting: "gistDescription" + }, + { + name: "GitHub Enterprise URL (optional)", + placeholder: "Enter GitHub Enterprise URL", + type: UISettingType.TextInput, + correspondingSetting: "githubEnterpriseUrl" + }, + { + name: "Ask Gist Name", + placeholder: "", + type: UISettingType.Checkbox, + correspondingSetting: "askGistName" + }, + { + name: "Download Public Gist", + placeholder: "", + type: UISettingType.Checkbox, + correspondingSetting: "downloadPublicGist" + }, + { + name: "Open Token Link", + placeholder: "", + type: UISettingType.Checkbox, + correspondingSetting: "openTokenLink" + } + ]; + + private extensionSettings = [ + { + name: "Gist ID", + placeholder: "Enter Gist ID", + type: UISettingType.TextInput, + correspondingSetting: "gist", + tooltip: localize("ext.config.gist") + }, + { + name: "Auto Download", + placeholder: "", + type: UISettingType.Checkbox, + correspondingSetting: "autoDownload", + tooltip: localize("ext.config.autoDownload") + }, + { + name: "Auto Upload", + placeholder: "", + type: UISettingType.Checkbox, + correspondingSetting: "autoUpload", + tooltip: localize("ext.config.autoUpload") + }, + { + name: "Force Download", + placeholder: "", + type: UISettingType.Checkbox, + correspondingSetting: "forceDownload", + tooltip: localize("ext.config.forceDownload") + }, + { + name: "Quiet Sync", + placeholder: "", + type: UISettingType.Checkbox, + correspondingSetting: "quietSync", + tooltip: localize("ext.config.quietSync") + }, + { + name: "Remove Extensions", + placeholder: "", + type: UISettingType.Checkbox, + correspondingSetting: "removeExtensions", + tooltip: localize("ext.config.removeExtensions") + }, + { + name: "Sync Extensions", + placeholder: "", + type: UISettingType.Checkbox, + correspondingSetting: "syncExtensions", + tooltip: localize("ext.config.syncExtensions") + } + ]; + constructor( private en: Environment, private context: vscode.ExtensionContext ) { this.InitializeAutoUpload(); + this.SettingsView = readFileSync( + `${this.context.extensionPath}/ui/settings/settings.html`, + { + encoding: "utf8" + } + ); + this.LandingPageView = readFileSync( + `${this.context.extensionPath}/ui/landing-page/landing-page.html`, + { + encoding: "utf8" + } + ); + } + + public async OpenSettingsPage() { + const customSettings = await this.GetCustomSettings(); + const extSettings = await this.GetSettings(); + const content: string = this.SettingsView.replace( + new RegExp("@GLOBAL_DATA", "g"), + JSON.stringify(customSettings) + ) + .replace(new RegExp("@ENV_DATA", "g"), JSON.stringify(extSettings)) + .replace( + new RegExp("@GLOBAL_MAP", "g"), + JSON.stringify(this.customizableSettings) + ) + .replace( + new RegExp("@ENV_MAP", "g"), + JSON.stringify(this.extensionSettings) + ) + .replace( + new RegExp("@PWD", "g"), + vscode.Uri.file(this.context.extensionPath) + .with({ + scheme: "vscode-resource" + }) + .toString() + ); + const settingsPanel = vscode.window.createWebviewPanel( + "syncSettings", + "Sync Settings", + vscode.ViewColumn.One, + { + retainContextWhenHidden: true, + enableScripts: true + } + ); + settingsPanel.webview.html = content; + settingsPanel.webview.onDidReceiveMessage(message => + this.ReceiveSettingChange(message) + ); + } + + public async ReceiveSettingChange(message: { + command: string; + text: string; + type: string; + }) { + let value: any = message.text; + if (message.text === "true" || message.text === "false") { + value = message.text === "true"; + } + if (message.type === "global") { + const customSettings = await this.GetCustomSettings(); + if (has(customSettings, message.command)) { + set(customSettings, message.command, value); + this.SetCustomSettings(customSettings); + } + } else { + const extSettings = await this.GetSettings(); + extSettings[message.command] = value; + this.SaveSettings(extSettings); + } + } + + public async OpenLandingPage() { + const releaseNotes = require("../release-notes.json"); + const content: string = this.LandingPageView.replace( + new RegExp("@PWD", "g"), + vscode.Uri.file(this.context.extensionPath) + .with({ + scheme: "vscode-resource" + }) + .toString() + ).replace("@RELEASE_NOTES", JSON.stringify(releaseNotes)); + const landingPanel = vscode.window.createWebviewPanel( + "landingPage", + "Welcome to Settings Sync", + vscode.ViewColumn.One, + { + retainContextWhenHidden: true, + enableScripts: true + } + ); + landingPanel.webview.html = content; + landingPanel.webview.onDidReceiveMessage(async message => { + switch (message.command) { + case "loginWithGitHub": + new GitHubOAuthService( + 54321, + this, + this.context.extensionPath + ).StartProcess(); + vscode.commands.executeCommand( + "vscode.open", + vscode.Uri.parse( + "https://github.com/login/oauth/authorize?scope=gist%20read:user&client_id=cfd96460d8b110e2351b&redirect_uri=http://localhost:54321/callback" + ) + ); + break; + case "editConfiguration": + this.OpenSettingsPage(); + break; + } + }); } public async InitializeAutoUpload() { @@ -110,47 +353,15 @@ export default class Commons { } } - public async InitalizeSettings( - askToken: boolean, - askGist: boolean - ): Promise { + public async InitalizeSettings(): Promise { const settings: LocalConfig = new LocalConfig(); const extSettings: ExtensionConfig = this.GetSettings(); const cusSettings: CustomSettings = await this.GetCustomSettings(); - if (cusSettings.token === "") { - if (askToken === true) { - askToken = !cusSettings.downloadPublicGist; - } - - if (askToken) { - if (cusSettings.openTokenLink) { - vscode.commands.executeCommand( - "vscode.open", - vscode.Uri.parse("https://github.com/settings/tokens") - ); - } - const tokTemp: string = await this.GetTokenAndSave(cusSettings); - if (!tokTemp) { - const msg = localize("common.error.tokenNotSave"); - vscode.window.showErrorMessage(msg); - throw new Error(msg); - } - cusSettings.token = tokTemp; - } + if (cusSettings.token === "" || extSettings.gist === "") { + this.OpenLandingPage(); } - if (extSettings.gist === "") { - if (askGist) { - const gistTemp: string = await this.GetGistAndSave(extSettings); - if (!gistTemp) { - const msg = localize("common.error.gistNotSave"); - vscode.window.showErrorMessage(msg); - throw new Error(msg); - } - extSettings.gist = gistTemp; - } - } settings.customConfig = cusSettings; settings.extConfig = extSettings; return settings; @@ -394,42 +605,6 @@ export default class Commons { return settings; } - public async GetTokenAndSave(sett: CustomSettings): Promise { - const opt = Commons.GetInputBox(true); - - const token = ((await vscode.window.showInputBox(opt)) || "").trim(); - - if (token && token !== "esc") { - sett.token = token; - const saved = await this.SetCustomSettings(sett); - if (saved) { - vscode.window.setStatusBarMessage( - localize("common.info.tokenSaved"), - 1000 - ); - } - } - - return token; - } - public async GetGistAndSave(sett: ExtensionConfig): Promise { - const opt = Commons.GetInputBox(false); - - const gist = ((await vscode.window.showInputBox(opt)) || "").trim(); - - if (gist && gist !== "esc") { - sett.gist = gist; - const saved = await this.SaveSettings(sett); - if (saved) { - vscode.window.setStatusBarMessage( - localize("common.info.gistSaved"), - 1000 - ); - } - return gist; - } - } - /** * IgnoreSettings */ diff --git a/src/models/settingType.model.ts b/src/models/settingType.model.ts new file mode 100644 index 00000000..1c6e8bf1 --- /dev/null +++ b/src/models/settingType.model.ts @@ -0,0 +1,5 @@ +export enum UISettingType { + TextInput, + Checkbox, + TextArea +} diff --git a/src/service/oauthService.ts b/src/service/oauthService.ts new file mode 100644 index 00000000..e1492357 --- /dev/null +++ b/src/service/oauthService.ts @@ -0,0 +1,114 @@ +import * as express from "express"; +import { readFileSync } from "fs"; +import { Server } from "http"; +import fetch from "node-fetch"; +import { URLSearchParams } from "url"; +import * as vscode from "vscode"; +import Commons from "../commons"; + +export class GitHubOAuthService { + public app: express.Express; + public server: Server; + public GistSelectionView: string; + + constructor( + public port: number, + public commons: Commons, + public extensionPath: string + ) { + this.app = express(); + this.app.use(express.json(), express.urlencoded({ extended: false })); + this.GistSelectionView = readFileSync( + `${this.extensionPath}/ui/gist-selection/gist-selection.html`, + { encoding: "utf8" } + ); + } + + public async StartProcess() { + this.server = this.app.listen(this.port); + this.app.get("/callback", async (req, res) => { + const params = new URLSearchParams( + await (await this.getToken(req.param("code"))).text() + ); + + res.send(""); + this.server.close(); + + const token = params.get("access_token"); + this.saveToken(token); + + const user = await this.getUser(token); + + const gists = await this.getGists(token, user); + this.saveGistId(gists); + }); + } + + public async getToken(code: string) { + const params = new URLSearchParams(); + params.append("client_id", "cfd96460d8b110e2351b"); + params.append("client_secret", "ed46bd3a0f736e0da57308e86ca5fa3cf8688582"); + params.append("code", code); + + return await fetch("https://github.com/login/oauth/access_token", { + method: "POST", + body: params + }); + } + + public async getGists(token: string, user: string) { + const res = await fetch(`https://api.github.com/users/${user}/gists`, { + method: "GET", + headers: { Authorization: `token ${token}` } + }); + const gists = await res.json(); + return gists; + } + + public async saveToken(token: string) { + const currentSettings = await this.commons.GetCustomSettings(); + currentSettings.token = token; + this.commons.SetCustomSettings(currentSettings); + } + + public async saveGistId(gists: any) { + const content: string = this.GistSelectionView.replace( + new RegExp("@GISTS", "g"), + JSON.stringify(gists) + ).replace( + new RegExp("@PWD", "g"), + vscode.Uri.file(this.extensionPath) + .with({ + scheme: "vscode-resource" + }) + .toString() + ); + const gistSelectionPanel = vscode.window.createWebviewPanel( + "selectGist", + "Select Your Existing Gist", + vscode.ViewColumn.One, + { + retainContextWhenHidden: true, + enableScripts: true + } + ); + gistSelectionPanel.webview.html = content; + gistSelectionPanel.webview.onDidReceiveMessage(async message => { + if (!message.close) { + const extSettings = await this.commons.GetSettings(); + extSettings.gist = message.id; + this.commons.SaveSettings(extSettings); + } + return gistSelectionPanel.dispose(); + }); + } + + public async getUser(token: string) { + const res = await fetch("https://api.github.com/user", { + method: "GET", + headers: { Authorization: `token ${token}` } + }); + const json = await res.json(); + return json.login; + } +} diff --git a/src/sync.ts b/src/sync.ts index cd498faa..f87e4f35 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -49,6 +49,11 @@ export class Sync { const gistAvailable: boolean = startUpSetting.gist != null && startUpSetting.gist !== ""; + if (!tokenAvailable) { + globalCommonService.OpenLandingPage(); + return; + } + if (gistAvailable) { if (startUpSetting.autoDownload) { vscode.commands @@ -88,7 +93,7 @@ export class Sync { await globalCommonService.HandleStopWatching(); try { - localConfig = await globalCommonService.InitalizeSettings(true, false); + localConfig = await globalCommonService.InitalizeSettings(); localConfig.publicGist = false; if (args.length > 0) { if (args[0] === "publicGIST") { @@ -385,7 +390,7 @@ export class Sync { await globalCommonService.HandleStopWatching(); try { - localSettings = await globalCommonService.InitalizeSettings(true, true); + localSettings = await globalCommonService.InitalizeSettings(); await StartDownload(localSettings.extConfig, localSettings.customConfig); } catch (err) { Commons.LogException(err, globalCommonService.ERROR_MESSAGE, true); @@ -756,6 +761,7 @@ export class Sync { const gistAvailable: boolean = setting.gist != null && setting.gist !== ""; const items: string[] = [ + "cmd.otherOptions.openSettingsPage", "cmd.otherOptions.editLocalSetting", "cmd.otherOptions.shareSetting", "cmd.otherOptions.downloadSetting", @@ -782,8 +788,11 @@ export class Sync { const index = items.findIndex(v => v === item); - const handlerMap = { - 0: async () => { + const handlerMap = [ + async () => { + common.OpenSettingsPage(); + }, + async () => { const file: vscode.Uri = vscode.Uri.file(env.FILE_CUSTOMIZEDSETTINGS); fs.openSync(file.fsPath, "r"); const document = await vscode.workspace.openTextDocument(file); @@ -793,7 +802,7 @@ export class Sync { true ); }, - 1: async () => { + async () => { // share public gist const answer = await vscode.window.showInformationMessage( localize("cmd.otherOptions.shareSetting.beforeConfirm"), @@ -809,26 +818,26 @@ export class Sync { await common.SetCustomSettings(customSettings); } }, - 2: async () => { + async () => { // Download Settings from Public GIST selectedItem = 2; customSettings.downloadPublicGist = true; settingChanged = true; await common.SetCustomSettings(customSettings); }, - 3: async () => { + async () => { // toggle force download selectedItem = 3; settingChanged = true; setting.forceDownload = !setting.forceDownload; }, - 4: async () => { + async () => { // toggle auto upload selectedItem = 4; settingChanged = true; setting.autoUpload = !setting.autoUpload; }, - 5: async () => { + async () => { // auto download on startup selectedItem = 5; settingChanged = true; @@ -843,7 +852,7 @@ export class Sync { setting.autoDownload = !setting.autoDownload; }, - 6: async () => { + async () => { // page summary toggle selectedItem = 6; settingChanged = true; @@ -854,7 +863,7 @@ export class Sync { } setting.quietSync = !setting.quietSync; }, - 7: async () => { + async () => { // add customized sync file const options: vscode.InputBoxOptions = { ignoreFocusOut: true, @@ -877,7 +886,7 @@ export class Sync { } } }, - 8: async () => { + async () => { // Import customized sync file to workspace const customFiles = await this.getCustomFilesFromGist( customSettings, @@ -921,7 +930,7 @@ export class Sync { } } }, - 9: async () => { + async () => { vscode.commands.executeCommand( "vscode.open", vscode.Uri.parse( @@ -929,7 +938,7 @@ export class Sync { ) ); }, - 10: async () => { + async () => { vscode.commands.executeCommand( "vscode.open", vscode.Uri.parse( @@ -937,7 +946,7 @@ export class Sync { ) ); }, - 11: async () => { + async () => { vscode.commands.executeCommand( "vscode.open", vscode.Uri.parse( @@ -945,7 +954,7 @@ export class Sync { ) ); } - }; + ]; try { await handlerMap[index](); diff --git a/ui/gist-selection/gist-selection.html b/ui/gist-selection/gist-selection.html new file mode 100644 index 00000000..c60e154e --- /dev/null +++ b/ui/gist-selection/gist-selection.html @@ -0,0 +1,69 @@ + + + + + + + + + + + +
+
+
+ +

+ Select Your Existing Gist +

+
+ Create a new Gist +
+
+
+ + + + + + + + diff --git a/ui/gist-selection/gist-selection.js b/ui/gist-selection/gist-selection.js new file mode 100644 index 00000000..31119f55 --- /dev/null +++ b/ui/gist-selection/gist-selection.js @@ -0,0 +1,60 @@ +// @ts-nocheck + +const vscode = acquireVsCodeApi(); + +/* https://stackoverflow.com/questions/3177836/how-to-format-time-since-xxx-e-g-4-minutes-ago-similar-to-stack-exchange-site */ +function timeSince(date) { + var seconds = Math.floor((new Date() - date) / 1000); + + var interval = Math.floor(seconds / 31536000); + + if (interval > 1) { + return interval + " years"; + } + interval = Math.floor(seconds / 2592000); + if (interval > 1) { + return interval + " months"; + } + interval = Math.floor(seconds / 86400); + if (interval > 1) { + return interval + " days"; + } + interval = Math.floor(seconds / 3600); + if (interval > 1) { + return interval + " hours"; + } + interval = Math.floor(seconds / 60); + if (interval > 1) { + return interval + " minutes"; + } + return Math.floor(seconds) + " seconds"; +} + +function appendHTML(parent, html) { + var div = document.createElement("div"); + div.innerHTML = html; + while (div.children.length > 0) { + parent.appendChild(div.children[0]); + } + div.remove(); +} + +function saveGistId(id) { + vscode.postMessage({ id }); +} + +const selectionContainer = document.getElementById("selectionContainer"); + +const selectionTemplate = ` +`; + +gists.forEach(gist => { + const html = selectionTemplate + .replace(new RegExp("@description", "g"), gist.description) + .replace(new RegExp("@id", "g"), gist.id) + .replace( + new RegExp("@timestamp", "g"), + timeSince(new Date(gist.updated_at)) + ); + appendHTML(selectionContainer, html); +}); diff --git a/ui/landing-page/landing-page.html b/ui/landing-page/landing-page.html new file mode 100644 index 00000000..5e06883d --- /dev/null +++ b/ui/landing-page/landing-page.html @@ -0,0 +1,160 @@ + + + + + + + + + + + +
+
+
+ +
+
+
+

+ What's New in + vX.X.X +

+
+
+
+
+

+ Configuration +

+

+ Login via GitHub to setup Settings Sync, or configure the + settings manually. +

+ Login with GitHub + Edit Configuration +
+
+

+ Show Your Support +

+

+ While being free and open source, if you find Settings Sync + useful, please consider supporting it by donating via PayPal + or Open Collective. +

+ Become a Sponsor + Donate via PayPal + +
+
+
+
+
+
+

+ Need Help? +

+ Homepage
+ Questions & Issues
+
+
+
+
+

+ Sponsors +

+

+ Settings Sync is looking for sponsors to display here. Contact + me on Twitter or + GitHub +

+
+
+
+
+
+
+ + + + + + + + diff --git a/ui/landing-page/landing-page.js b/ui/landing-page/landing-page.js new file mode 100644 index 00000000..2a2a79cc --- /dev/null +++ b/ui/landing-page/landing-page.js @@ -0,0 +1,33 @@ +// @ts-nocheck +const vscode = acquireVsCodeApi(); + +function sendCommand(args) { + vscode.postMessage({ + command: args + }); +} + +function appendHTML(parent, html) { + var div = document.createElement("div"); + div.innerHTML = html; + while (div.children.length > 0) { + parent.appendChild(div.children[0]); + } + div.remove(); +} + +const releaseNoteTemplate = `
@TYPE@NOTE (Thanks to @@AUTHOR for PR #@PR)
`; + +const notesElement = document.getElementById("notes"); +releaseNotes.changes.forEach(change => { + const html = releaseNoteTemplate + .replace(new RegExp("@NOTE", "g"), change.details) + .replace(new RegExp("@TYPE", "g"), change.type) + .replace(new RegExp("@COLOR", "g"), change.color) + .replace(new RegExp("@AUTHOR", "g"), change.author) + .replace(new RegExp("@PR", "g"), change.pullRequest); + appendHTML(notesElement, html); +}); + +const currentVersionElement = document.getElementById("current-version"); +currentVersionElement.innerHTML = releaseNotes.currentVersion; diff --git a/ui/settings/settings.html b/ui/settings/settings.html new file mode 100644 index 00000000..8fb54141 --- /dev/null +++ b/ui/settings/settings.html @@ -0,0 +1,89 @@ + + + + + + + + + + + + +
+
+
+ +
+
+

+ Environment Settings +

+
+

+
+
+

+ Global Settings +

+
+
+
+
+
+
+ + + + + + + + + diff --git a/ui/settings/settings.js b/ui/settings/settings.js new file mode 100644 index 00000000..f08e5c37 --- /dev/null +++ b/ui/settings/settings.js @@ -0,0 +1,187 @@ +// @ts-nocheck + +function appendHTML(parent, html) { + var div = document.createElement("div"); + div.innerHTML = html; + while (div.children.length > 0) { + parent.appendChild(div.children[0]); + } + div.remove(); +} + +const vscode = acquireVsCodeApi(); + +const textInputTemplate = `
+ + @tooltip + +
`; + +const checkboxTemplate = `
+ + + @tooltip +
`; + +const textareaTemplate = `
+ + @tooltip + +
`; + +const globalParent = document.getElementById("globalSettings"); +const envParent = document.getElementById("environmentSettings"); +const saveStatus = document.getElementById("saveStatus"); + +globalMap.forEach(settingMap => { + let template; + switch (settingMap.type) { + case 0: + template = textInputTemplate; + break; + case 1: + template = checkboxTemplate; + break; + case 2: + template = textareaTemplate; + break; + } + const html = template + .replace(new RegExp("@name", "g"), settingMap.name) + .replace(new RegExp("@placeholder", "g"), settingMap.placeholder) + .replace( + new RegExp("@correspondingSetting", "g"), + settingMap.correspondingSetting + ) + .replace(new RegExp("@tooltip"), "") + .replace(new RegExp("@settingType", "g"), "global"); + appendHTML(globalParent, html); +}); + +envMap.forEach(envMap => { + let template; + switch (envMap.type) { + case 0: + template = textInputTemplate; + break; + case 1: + template = checkboxTemplate; + break; + } + const html = template + .replace(new RegExp("@name", "g"), envMap.name) + .replace(new RegExp("@placeholder", "g"), envMap.placeholder) + .replace( + new RegExp("@correspondingSetting", "g"), + envMap.correspondingSetting + ) + .replace( + new RegExp("@tooltip"), + `` + ) + .replace(new RegExp("@settingType", "g"), "env"); + appendHTML(envParent, html); +}); + +$(document).ready(function() { + save(); + $('[data-toggle="tooltip"]').tooltip(); + $(".text") + .each((i, el) => { + if ($(el).attr("settingType") === "global") { + $(el).val(_.get(globalData, $(el).attr("setting"))); + } else { + $(el).val(envData[$(el).attr("setting")]); + } + }) + .change(function() { + save(); + let val = $(this).val(); + vscode.postMessage({ + command: $(this).attr("setting"), + text: val, + type: $(this).attr("settingType") + }); + }); + $(".checkbox") + .each((i, el) => { + if ($(el).attr("settingType") === "global") { + $(el).prop("checked", _.get(globalData, $(el).attr("setting"))); + } else { + $(el).prop("checked", envData[$(el).attr("setting")]); + } + }) + .change(function() { + save(); + let val = $(this).is(":checked"); + vscode.postMessage({ + command: $(this).attr("setting"), + text: val, + type: $(this).attr("settingType") + }); + }); + $(".textarea") + .each((i, el) => { + let str = ""; + const items = _.get(globalData, $(el).attr("setting")); + items.forEach(item => (str += item + "\n")); + $(el).val(str.slice(0, -1)); + $(el).prop("rows", items.length); + }) + .change(function() { + save(); + let val = []; + $(this) + .val() + .split("\n") + .forEach(item => { + if (item !== "") { + val.push(item); + } + }); + vscode.postMessage({ + command: $(this).attr("setting"), + text: val, + type: "global" + }); + }); +}); + +function save() { + saveStatus.innerHTML = ``; + setTimeout( + () => + (saveStatus.innerHTML = ``), + 1000 + ); +} diff --git a/ui/shared/page-header.js b/ui/shared/page-header.js new file mode 100644 index 00000000..450189d3 --- /dev/null +++ b/ui/shared/page-header.js @@ -0,0 +1,19 @@ +document.querySelector( + "page-header" +).innerHTML = `

+ +Settings Sync +

+

+Synchronize Settings, Snippets, Themes, File Icons, Launch, +Keybindings, Workspaces and Extensions Across Multiple Machines +Using GitHub Gist +

+

+by @shanalikhan +

`; diff --git a/ui/shared/styles.css b/ui/shared/styles.css new file mode 100644 index 00000000..013c6495 --- /dev/null +++ b/ui/shared/styles.css @@ -0,0 +1,129 @@ +:root { + --btn: #0e629c; + --btn-hover: #15496e; + --btn-click: #0e3450; +} +#selectionContainer { + width: 60%; +} +.dock-bottom-left { + position: fixed; + bottom: 4rem; + left: 4rem; +} +html, +body { + background-color: rgb(10, 1, 15); + font-family: "Roboto", sans-serif !important; + color: white; + letter-spacing: 0.0625em; +} +.logo { + vertical-align: -4px; +} +.change { + line-height: 150%; +} +.badge-success { + color: #fff; + background-color: #73c991; +} +.badge-danger { + color: #fff; + background-color: #ce4f59; +} +.badge { + vertical-align: 2px; + width: 6rem; +} +.opacity-50 { + filter: opacity(0.5); + -webkit-filter: opacity(0.5); +} +.scrollable { + overflow-y: auto; + height: 35rem; +} +.masthead { + position: relative; + width: 100%; + height: auto; + min-height: 35rem; + padding: 15rem 0; + background-position: center; + background-repeat: no-repeat; + background-attachment: scroll; + background-size: cover; + margin-top: 40px; + margin-bottom: 40px; +} +.masthead h1 { + font-size: 2.5rem; + line-height: 2.5rem; + font-weight: bold; + font-family: "Open Sans"; +} +.masthead h2 { + /* max-width: 20rem; */ + font-size: 1rem; +} +@media (min-width: 768px) { + .masthead h1 { + font-size: 4rem; + line-height: 4rem; + } +} +@media (min-width: 992px) { + .masthead { + /* height: 100vh; */ + padding: 0; + } + .masthead h1 { + font-size: 6.5rem; + line-height: 6.5rem; + } + .masthead h2 { + /* max-width: 30rem; */ + font-size: 1.25rem; + } +} +.btn { + -webkit-box-shadow: 0 0.1875rem 0.1875rem 0 rgba(0, 0, 0, 0.1) !important; + box-shadow: 0 0.1875rem 0.1875rem 0 rgba(0, 0, 0, 0.1) !important; + padding: 1.25rem 2rem; + font-size: 80%; + text-transform: uppercase; + letter-spacing: 0.15rem; + border: 0; +} +.btn-primary { + background-color: var(--btn); +} +.btn-primary:hover { + background-color: var(--btn-hover); +} +.btn-primary:focus { + background-color: var(--btn-hover); + color: #fff; +} +.btn-primary:active { + background-color: var(--btn-click) !important; +} +.text, +.textarea { + -webkit-box-shadow: 0 0.1875rem 0.1875rem 0 rgba(0, 0, 0, 0.1) !important; + box-shadow: 0 0.1875rem 0.1875rem 0 rgba(0, 0, 0, 0.1) !important; + padding: 1.25rem 2rem; + height: auto; + border: 0; +} +a { + /* color: #64a19d; */ + color: var(--btn); +} +a:focus, +a:hover { + text-decoration: none; + /* color: #3c6360; */ + color: var(--btn-hover); +} From a387c23cc0f6ebd43c8295140914163d31aabd51 Mon Sep 17 00:00:00 2001 From: Nilesh Kevlani Date: Mon, 6 May 2019 16:07:02 +0530 Subject: [PATCH 04/64] #800 #515 #854 * Utilized pragmaUtil Functions for kb.json file * Typo fix * Added universalKeybindings setting --- src/pragmaUtil.ts | 8 ++++---- src/setting.ts | 1 + src/sync.ts | 45 ++++++++++++++++++++++++++++++--------------- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/pragmaUtil.ts b/src/pragmaUtil.ts index 1d76864e..d6267fb1 100644 --- a/src/pragmaUtil.ts +++ b/src/pragmaUtil.ts @@ -118,12 +118,12 @@ export default class PragmaUtil { * Remove @sync-ignore settings before upload. * * @static - * @param {string} settingsContent + * @param {string} fileContent * @returns {string} * @memberof PragmaUtil */ - public static processBeforeUpload(settingsContent: string): string { - const lines = settingsContent.split("\n"); + public static processBeforeUpload(fileContent: string): string { + const lines = fileContent.split("\n"); let osMatch: RegExpMatchArray; let osFromPragma: string; @@ -258,7 +258,7 @@ export default class PragmaUtil { parsedLines.push(this.toggleComments(currentLine, shouldComment)); } - const opensCurlyBraces = /".+"\s*:\s*{/.test(currentLine); + const opensCurlyBraces = /{/.test(currentLine); const opensBrackets = /".+"\s*:\s*\[/.test(currentLine); let openedBlock = opensCurlyBraces || opensBrackets; diff --git a/src/setting.ts b/src/setting.ts index 0efa77e6..88231e61 100644 --- a/src/setting.ts +++ b/src/setting.ts @@ -57,4 +57,5 @@ export class CustomSettings { public askGistName: boolean = false; public customFiles: { [key: string]: string } = {}; public hostName: string = null; + public universalKeybindings: boolean = false; } diff --git a/src/sync.ts b/src/sync.ts index cd498faa..aef90aeb 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -221,7 +221,8 @@ export class Sync { if (snippetFile.content !== "") { if (snippetFile.fileName === env.FILE_KEYBINDING_NAME) { snippetFile.gistName = - env.OsType === OsType.Mac + env.OsType === OsType.Mac && + !customSettings.universalKeybindings ? env.FILE_KEYBINDING_MAC : env.FILE_KEYBINDING_DEFAULT; } @@ -229,7 +230,11 @@ export class Sync { } } - if (snippetFile.fileName === env.FILE_SETTING_NAME) { + if ( + snippetFile.fileName === env.FILE_SETTING_NAME || + snippetFile.fileName === env.FILE_KEYBINDING_MAC || + snippetFile.fileName === env.FILE_KEYBINDING_DEFAULT + ) { try { snippetFile.content = PragmaUtil.processBeforeUpload( snippetFile.content @@ -485,17 +490,23 @@ export class Sync { ); updatedFiles.push(f); } else if (gistName.indexOf(".") > -1) { - if ( - env.OsType === OsType.Mac && - gistName === env.FILE_KEYBINDING_DEFAULT - ) { - return; - } - if ( - env.OsType !== OsType.Mac && - gistName === env.FILE_KEYBINDING_MAC - ) { - return; + if (customSettings.universalKeybindings) { + if (gistName === env.FILE_KEYBINDING_MAC) { + return; + } + } else { + if ( + env.OsType === OsType.Mac && + gistName === env.FILE_KEYBINDING_DEFAULT + ) { + return; + } + if ( + env.OsType !== OsType.Mac && + gistName === env.FILE_KEYBINDING_MAC + ) { + return; + } } const f: File = new File( gistName, @@ -583,7 +594,7 @@ export class Sync { file.gistName === env.FILE_KEYBINDING_MAC ) { let test: string = ""; - env.OsType === OsType.Mac + env.OsType === OsType.Mac && !customSettings.universalKeybindings ? (test = env.FILE_KEYBINDING_MAC) : (test = env.FILE_KEYBINDING_DEFAULT); if (file.gistName !== test) { @@ -604,7 +615,11 @@ export class Sync { ); } - if (file.gistName === env.FILE_SETTING_NAME) { + if ( + file.gistName === env.FILE_SETTING_NAME || + file.gistName === env.FILE_KEYBINDING_MAC || + file.gistName === env.FILE_KEYBINDING_DEFAULT + ) { const localContent = await FileService.ReadFile(filePath); content = PragmaUtil.processBeforeWrite( localContent, From d946e4786145bc961cb0fd85a0613013bf7171cb Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 6 May 2019 15:40:18 +0500 Subject: [PATCH 05/64] chore(package): update @types/node to version 12.0.0 (#873) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e99e4b82..5d47b1de 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "@types/chai": "4.1.7", "@types/fs-extra": "^5.0.5", "@types/mocha": "^5.2.6", - "@types/node": "^11.13.0", + "@types/node": "^12.0.0", "chai": "^4.2.0", "clean-webpack-plugin": "^2.0.1", "mocha": "^6.0.2", From 711c4de654571ae911d01f0992203b7254049e8e Mon Sep 17 00:00:00 2001 From: Michael Barros <93akkord@gmail.com> Date: Mon, 6 May 2019 06:43:19 -0400 Subject: [PATCH 06/64] Cleaned up toggling commented settings (#877) * Cleaned up toggling commented settings * Updated to include fix by @ioprotium --- src/pragmaUtil.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/pragmaUtil.ts b/src/pragmaUtil.ts index d6267fb1..5ff8659c 100644 --- a/src/pragmaUtil.ts +++ b/src/pragmaUtil.ts @@ -232,10 +232,14 @@ export default class PragmaUtil { private static readonly EnvPragmaWhiteSpacesSupportRegExp = /(?:env=(.+)host=)|(?:env=(.+)os=)|env=(.+)\n?/; private static toggleComments(line: string, shouldComment: boolean) { - if (shouldComment && !line.trim().startsWith("//")) { - return " //" + line; // 2 spaces as formmating + const isCommented = line.trim().startsWith("//"); + + if (shouldComment) { + // Replace with RegEx to help match indent size + return !isCommented ? line.replace(/^(\s*)/, "$1// ") : line; } else { - return line.replace("//", ""); + // Only remove if line is commented + return isCommented ? line.replace(/\/\/\s*/, "") : line; } } From fdc550dc08b31ed0062a578f03e7c88abe8042e6 Mon Sep 17 00:00:00 2001 From: Arno Hovhannisyan Date: Thu, 9 May 2019 18:19:07 -0700 Subject: [PATCH 07/64] Fix warning with webpack --- configs/webpack.config.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/configs/webpack.config.js b/configs/webpack.config.js index 1ab26663..f58ac3b3 100644 --- a/configs/webpack.config.js +++ b/configs/webpack.config.js @@ -2,7 +2,7 @@ const path = require("path"); const CleanWebpackPlugin = require("clean-webpack-plugin").default; -const webpack = require("webpack"); +const nodeExternals = require("webpack-node-externals"); /** @type WebpackOptions */ const config = { @@ -17,7 +17,10 @@ const config = { resolve: { extensions: [".ts", ".js"], alias: { - deepmerge$: path.resolve(__dirname, "../node_modules/deepmerge/dist/umd.js") + deepmerge$: path.resolve( + __dirname, + "../node_modules/deepmerge/dist/umd.js" + ) } }, module: { @@ -29,11 +32,14 @@ const config = { } ] }, - externals: { - vscode: "commonjs vscode", - "vscode-fsevents": "commonjs vscode-fsevents", - "original-fs": "commonjs original-fs" - }, + externals: [ + { + vscode: "commonjs vscode", + "vscode-fsevents": "commonjs vscode-fsevents", + "original-fs": "commonjs original-fs" + }, + nodeExternals() + ], plugins: [new CleanWebpackPlugin()] }; From e2680e4cab40be44fc66ecffea42842cbd5f629c Mon Sep 17 00:00:00 2001 From: Arno Hovhannisyan Date: Thu, 9 May 2019 20:00:28 -0700 Subject: [PATCH 08/64] Update UI --- release-notes.json | 10 +-- ui/gist-selection/gist-selection.html | 4 +- ui/landing-page/landing-page.html | 110 +++++++++++++++----------- ui/settings/settings.html | 8 +- ui/settings/settings.js | 14 ++-- ui/shared/page-header.js | 12 +-- ui/shared/styles.css | 49 ++++++------ 7 files changed, 110 insertions(+), 97 deletions(-) diff --git a/release-notes.json b/release-notes.json index 190e26a8..05e8dbac 100644 --- a/release-notes.json +++ b/release-notes.json @@ -1,35 +1,35 @@ { "changes": [ { - "details": "Fixed Code that kills Extension Host for MacOS", + "details": "Fixed Code that kills Extension Host for macOS", "type": "FIX", "color": "danger", "author": "arnohovhannisyan", "pullRequest": "834" }, { - "details": "Download From Public Gist not working", + "details": "Download From Public Gist not working", "type": "FIX", "color": "danger", "author": "shanalikhan", "pullRequest": "816" }, { - "details": "Auto Upload Fix", + "details": "Auto Upload Fix", "type": "FIX", "color": "danger", "author": "arnohovhannisyan", "pullRequest": "835" }, { - "details": "Inserts some empty lines in the beginning of settings.json", + "details": "Inserts some empty lines in the beginning of settings.json", "type": "NEW", "color": "success", "author": "knyhle", "pullRequest": "828" }, { - "details": "Update Documentation", + "details": "Update Documentation", "type": "NEW", "color": "success", "author": "colinaaa", diff --git a/ui/gist-selection/gist-selection.html b/ui/gist-selection/gist-selection.html index c60e154e..91b0f3ed 100644 --- a/ui/gist-selection/gist-selection.html +++ b/ui/gist-selection/gist-selection.html @@ -13,7 +13,7 @@ crossorigin="anonymous" />
-

+

Select Your Existing Gist

diff --git a/ui/landing-page/landing-page.html b/ui/landing-page/landing-page.html index 5e06883d..bcccce81 100644 --- a/ui/landing-page/landing-page.html +++ b/ui/landing-page/landing-page.html @@ -13,7 +13,7 @@ crossorigin="anonymous" />
-

+

What's New in - vX.X.X + + vX.X.X + +

-

+

Configuration

-

+

Login via GitHub to setup Settings Sync, or configure the settings manually.

- Login with GitHub - Edit Configuration +
-

+

Show Your Support

-

- While being free and open source, if you find Settings Sync +

+ While being free and open source, if you find + Settings Sync useful, please consider supporting it by donating via PayPal or Open Collective.

- Become a Sponsor - Donate via PayPal + +
Write a reviewWrite a Review
Star or Fork Settings Sync on Github
-

+

Need Help?

Homepage
@@ -119,10 +137,10 @@

-

+

Sponsors

-

+

Settings Sync is looking for sponsors to display here. Contact me on Twitter or GitHub diff --git a/ui/settings/settings.html b/ui/settings/settings.html index 8fb54141..a74eea11 100644 --- a/ui/settings/settings.html +++ b/ui/settings/settings.html @@ -13,7 +13,7 @@ crossorigin="anonymous" />

-

+

Environment Settings

-

+

Global Settings

diff --git a/ui/settings/settings.js b/ui/settings/settings.js index f08e5c37..73a5a6dc 100644 --- a/ui/settings/settings.js +++ b/ui/settings/settings.js @@ -11,8 +11,8 @@ function appendHTML(parent, html) { const vscode = acquireVsCodeApi(); -const textInputTemplate = `
-