From 01bfde1f5321e4d4fff3728923f509d614031e4f Mon Sep 17 00:00:00 2001 From: Plague Fox Date: Fri, 23 Aug 2024 15:28:48 +0400 Subject: [PATCH 1/4] feat: Add support for Flutter Plus extension activation and SDK commands This commit adds support for activating the Flutter Plus extension and registering SDK commands. It ensures that the required Dart and Flutter extensions are installed and activated before proceeding. If any of the extensions are missing or fail to activate, an error message is displayed. The SDK commands are registered using the `registerCommands` function, which is called during extension activation. The `registerCommands` function registers the `flutter-plus.sealed-states` command. Additionally, the commit registers wrappers for the "Wrap with..." functionality using the `registerWrappers` function. The wrappers registered include `flutter-plus.wrap-sizedbox`, `flutter-plus.wrap-listenablebuilder`, `flutter-plus.wrap-valuelistenablebuilder`, and `flutter-plus.wrap-repaintboundary`. This commit also introduces a new `SdkCommands` class in the `src/utils/sdk.ts` file. The `SdkCommands` class handles the registration and execution of SDK commands. It takes the `dartExtensionApi` as a parameter and uses it to run the desired function if it is supported. If the function is not available, an error message is displayed. The changes in this commit aim to enhance the functionality and usability of the Flutter Plus extension by adding support for activation and SDK commands. --- package.json | 66 +++++++++++++++++++++++++++++++++++------- src/constants/index.ts | 2 ++ src/extension.ts | 47 ++++++++++++++++++++++++++++-- src/utils/sdk.ts | 23 +++++++++++++++ 4 files changed, 125 insertions(+), 13 deletions(-) create mode 100644 src/constants/index.ts create mode 100644 src/utils/sdk.ts diff --git a/package.json b/package.json index 6ecb2de..564dbc3 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,19 @@ "engines": { "vscode": "^1.92.0" }, + "extensionKind": [ + "workspace" + ], + "capabilities": { + "virtualWorkspaces": { + "supported": "limited", + "description": "Some functionality may be limited for remote files in virtual workspaces." + }, + "untrustedWorkspaces": { + "supported": false + } + }, + "license": "SEE LICENSE IN LICENSE", "publisher": "plugfox", "bugs": { "url": "https://github.com/PlugFox/flutter-plus/issues", @@ -23,39 +36,66 @@ "Programming Languages" ], "keywords": [ - "dart", - "flutter", - "snippets", - "fox" + "Programming Languages", + "Snippets", + "Linters", + "Formatters", + "Debuggers", + "Dart", + "Flutter", + "Actions", + "Shortcuts" ], "activationEvents": [ - "onCommand:extension.sealed-states", - "workspaceContains:**/pubspec.yaml" + "onLanguage:dart", + "workspaceContains:pubspec.yaml", + "workspaceContains:*/pubspec.yaml", + "workspaceContains:*/*/pubspec.yaml", + "workspaceContains:*.dart", + "workspaceContains:*/*.dart", + "workspaceContains:*/*/*.dart", + "onCommand:flutter.createProject", + "onCommand:dart.createProject", + "onUri" ], "main": "./dist/extension.js", "contributes": { "commands": [ { "command": "flutter-plus.sealed-states", - "title": "Create Sealed States" + "title": "Create Sealed States", + "category": "Flutter Plus" }, { "command": "flutter-plus.wrap-sizedbox", - "title": "Wrap with SizedBox" + "title": "Wrap with SizedBox", + "category": "Flutter Plus" }, { "command": "flutter-plus.wrap-listenablebuilder", - "title": "Wrap with ListenableBuilder" + "title": "Wrap with ListenableBuilder", + "category": "Flutter Plus" }, { "command": "flutter-plus.wrap-valuelistenablebuilder", - "title": "Wrap with ValueListenableBuilder" + "title": "Wrap with ValueListenableBuilder", + "category": "Flutter Plus" }, { "command": "flutter-plus.wrap-repaintboundary", - "title": "Wrap with RepaintBoundary" + "title": "Wrap with RepaintBoundary", + "category": "Flutter Plus" } ], + "views": { + "flutter": [ + { + "id": "flutter-plus.sidebarActions", + "name": "Actions", + "when": "dart-code:anyFlutterProjectLoaded" + } + ] + }, "submenus": [ { "id": "flutter-plus.submenu", @@ -94,6 +134,10 @@ } ] }, + "extensionDependencies": [ + "Dart-Code.dart-code", + "Dart-Code.flutter" + ], "scripts": { "compile": "npm run check-types && npm run lint && node esbuild.js", "watch": "npm-run-all -p watch:*", diff --git a/src/constants/index.ts b/src/constants/index.ts new file mode 100644 index 0000000..0fdd491 --- /dev/null +++ b/src/constants/index.ts @@ -0,0 +1,2 @@ +export const dartCodeExtensionIdentifier = "Dart-Code.dart-code"; +export const flutterExtensionIdentifier = "Dart-Code.flutter"; \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 165ef45..72b3f2c 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -17,21 +17,64 @@ import { CodeActionWrap, } from './code-actions'; + +import { + dartCodeExtensionIdentifier, + flutterExtensionIdentifier, +} from "./constants"; +import { SdkCommands } from './utils/sdk'; + const DART_MODE = { language: "dart", scheme: "file" }; -export function activate(context: vscode.ExtensionContext) { +export async function activate(context: vscode.ExtensionContext): Promise { + // Ensure we have a Dart extension. + const dartExt = vscode.extensions.getExtension(dartCodeExtensionIdentifier); + if (!dartExt) { + // This should not happen since the Flutter extension has a dependency on the Dart one + // but just in case, we'd like to give a useful error message. + throw new Error("The Dart extension is not installed, Flutter extension is unable to activate."); + } + await dartExt.activate(); + if (!dartExt.exports) { + console.error("The Dart extension did not provide an exported API. Maybe it failed to activate or is not the latest version?"); + return; + } + + // Ensure we have a Flutter extension. + const flutterExt = vscode.extensions.getExtension(flutterExtensionIdentifier); + if (!flutterExt) { + // This should not happen since the Flutter extension has a dependency on the Dart one + // but just in case, we'd like to give a useful error message. + throw new Error("The Flutter extension is not installed, Flutter Plus extension is unable to activate."); + } + await flutterExt.activate(); + + // Register SDK commands. + const sdkCommands = new SdkCommands(context, dartExt.exports); + //console.log('Congratulations, your extension "flutter-plus" is now active!'); + registerCommands(context); + registerWrappers(context); +} + +/// Register all commands. +function registerCommands(context: vscode.ExtensionContext) { context.subscriptions.push( /* vscode.commands.registerCommand('flutter-plus.helloWorld', () => { vscode.window.showInformationMessage('Hello World from Flutter Plus!'); }), */ commands.registerCommand("flutter-plus.sealed-states", sealedStates), + ); +} + +/// Register all wrappers (Wrap With...). +function registerWrappers(context: vscode.ExtensionContext) { + context.subscriptions.push( commands.registerCommand("flutter-plus.wrap-sizedbox", wrapWithSizedBox), commands.registerCommand("flutter-plus.wrap-listenablebuilder", wrapWithListenableBuilder), commands.registerCommand("flutter-plus.wrap-valuelistenablebuilder", wrapWithValueListenableBuilder), commands.registerCommand("flutter-plus.wrap-repaintboundary", wrapWithRepaintBoundary), - languages.registerCodeActionsProvider( DART_MODE, new CodeActionWrap(), diff --git a/src/utils/sdk.ts b/src/utils/sdk.ts new file mode 100644 index 0000000..1bc3364 --- /dev/null +++ b/src/utils/sdk.ts @@ -0,0 +1,23 @@ +import * as vscode from "vscode"; + +export class SdkCommands { + // TODO: Find an easy way to share the API signature class. + constructor(context: vscode.ExtensionContext, private dartExtensionApi: any) { + + // context.subscriptions.push(vs.commands.registerCommand("flutter.createSampleProject", + // (_) => this.runFunctionIfSupported(dartExtensionApi.flutterCreateSampleProject))); + } + + private async runFunctionIfSupported(f: () => Promise): Promise { + if (!f) { + this.showApiMismatchError(); + return undefined; + } + + return f(); + } + + private showApiMismatchError(): void { + vscode.window.showErrorMessage("The installed version of the Dart extension does not support this feature."); + } +} \ No newline at end of file From 04ff2905fa20d38a8f91212f550fb4a5dc106926 Mon Sep 17 00:00:00 2001 From: Plague Fox Date: Fri, 23 Aug 2024 15:57:53 +0400 Subject: [PATCH 2/4] feat: Add support for Flutter Plus extension activation and SDK commands --- package.json | 7 +++++- src/extension.ts | 42 +++++++++++++++++++++++++----------- src/utils/execute-command.ts | 8 +++++++ src/utils/index.ts | 3 +++ 4 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 src/utils/execute-command.ts diff --git a/package.json b/package.json index 564dbc3..b4fd309 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,11 @@ "main": "./dist/extension.js", "contributes": { "commands": [ + { + "command": "flutter-plus.pub-get", + "title": "Pub Get", + "category": "Flutter Plus" + }, { "command": "flutter-plus.sealed-states", "title": "Create Sealed States", @@ -90,7 +95,7 @@ "views": { "flutter": [ { - "id": "flutter-plus.sidebarActions", + "id": "flutter-plus.sidebar-actions", "name": "Actions", "when": "dart-code:anyFlutterProjectLoaded" } diff --git a/src/extension.ts b/src/extension.ts index 72b3f2c..d8b37f9 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,10 +1,5 @@ import * as vscode from 'vscode'; -import { - commands, - languages -} from "vscode"; - import { sealedStates, wrapWithListenableBuilder, @@ -22,7 +17,13 @@ import { dartCodeExtensionIdentifier, flutterExtensionIdentifier, } from "./constants"; -import { SdkCommands } from './utils/sdk'; + +/* import fs from 'fs'; +import path from 'path'; */ + +import { + SdkCommands, +} from './utils'; const DART_MODE = { language: "dart", scheme: "file" }; @@ -55,6 +56,7 @@ export async function activate(context: vscode.ExtensionContext): Promise //console.log('Congratulations, your extension "flutter-plus" is now active!'); registerCommands(context); + //registerActionButtons(context); registerWrappers(context); } @@ -64,18 +66,34 @@ function registerCommands(context: vscode.ExtensionContext) { /* vscode.commands.registerCommand('flutter-plus.helloWorld', () => { vscode.window.showInformationMessage('Hello World from Flutter Plus!'); }), */ - commands.registerCommand("flutter-plus.sealed-states", sealedStates), + vscode.commands.registerCommand("flutter-plus.sealed-states", sealedStates), ); } +/* function registerActionButtons(context: vscode.ExtensionContext) { + function runPubGet() { + // Example of running `dart pub get` or `flutter pub get` + const pubspecPath = path.join(vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || '', 'pubspec.yaml'); + if (fs.existsSync(pubspecPath)) { + const pubspecContent = fs.readFileSync(pubspecPath, 'utf8'); + const isFlutterApp = pubspecContent.includes('flutter:'); + const command = isFlutterApp ? 'flutter pub get' : 'dart pub get'; + executeCommand(command); + } + } + context.subscriptions.push(vscode.commands.registerCommand('flutter-plus.pub-get', () => { + runPubGet(); + })); +} */ + /// Register all wrappers (Wrap With...). function registerWrappers(context: vscode.ExtensionContext) { context.subscriptions.push( - commands.registerCommand("flutter-plus.wrap-sizedbox", wrapWithSizedBox), - commands.registerCommand("flutter-plus.wrap-listenablebuilder", wrapWithListenableBuilder), - commands.registerCommand("flutter-plus.wrap-valuelistenablebuilder", wrapWithValueListenableBuilder), - commands.registerCommand("flutter-plus.wrap-repaintboundary", wrapWithRepaintBoundary), - languages.registerCodeActionsProvider( + vscode.commands.registerCommand("flutter-plus.wrap-sizedbox", wrapWithSizedBox), + vscode.commands.registerCommand("flutter-plus.wrap-listenablebuilder", wrapWithListenableBuilder), + vscode.commands.registerCommand("flutter-plus.wrap-valuelistenablebuilder", wrapWithValueListenableBuilder), + vscode.commands.registerCommand("flutter-plus.wrap-repaintboundary", wrapWithRepaintBoundary), + vscode.languages.registerCodeActionsProvider( DART_MODE, new CodeActionWrap(), ), diff --git a/src/utils/execute-command.ts b/src/utils/execute-command.ts new file mode 100644 index 0000000..0e70af2 --- /dev/null +++ b/src/utils/execute-command.ts @@ -0,0 +1,8 @@ +import * as vscode from 'vscode'; + +// Execute a command in the terminal +export function executeCommand(command: string) { + const terminal = vscode.window.createTerminal('Flutter Plus'); + terminal.sendText(command); + terminal.show(); +} \ No newline at end of file diff --git a/src/utils/index.ts b/src/utils/index.ts index f26196e..7f33895 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,2 +1,5 @@ +export * from "./execute-command"; export * from "./get-selected-text"; +export * from "./sdk"; export * from "./wrap-with"; + From 74b400a7a031ed3ec44ed2a9ce2374dcd0240a01 Mon Sep 17 00:00:00 2001 From: Plague Fox Date: Fri, 23 Aug 2024 16:00:20 +0400 Subject: [PATCH 3/4] Exclude pub get from package.json --- package.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package.json b/package.json index b4fd309..85b29bd 100644 --- a/package.json +++ b/package.json @@ -61,11 +61,6 @@ "main": "./dist/extension.js", "contributes": { "commands": [ - { - "command": "flutter-plus.pub-get", - "title": "Pub Get", - "category": "Flutter Plus" - }, { "command": "flutter-plus.sealed-states", "title": "Create Sealed States", From 3116a333b2a55a9dce259280cd722bb3347ed76f Mon Sep 17 00:00:00 2001 From: Plague Fox Date: Fri, 23 Aug 2024 16:06:03 +0400 Subject: [PATCH 4/4] chore: Update GitHub Actions workflow to include only Ubuntu as the operating system --- .github/workflows/checkout.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/checkout.yml b/.github/workflows/checkout.yml index ba6d9e9..15ec2e7 100644 --- a/.github/workflows/checkout.yml +++ b/.github/workflows/checkout.yml @@ -27,7 +27,10 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-latest, ubuntu-latest, windows-latest] + os: + - ubuntu-latest + #- macos-latest + #- windows-latest runs-on: ${{ matrix.os }} defaults: run: