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: diff --git a/package.json b/package.json index 6ecb2de..85b29bd 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.sidebar-actions", + "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..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, @@ -17,22 +12,88 @@ import { CodeActionWrap, } from './code-actions'; + +import { + dartCodeExtensionIdentifier, + flutterExtensionIdentifier, +} from "./constants"; + +/* import fs from 'fs'; +import path from 'path'; */ + +import { + SdkCommands, +} from './utils'; + 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); + //registerActionButtons(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), - 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), + vscode.commands.registerCommand("flutter-plus.sealed-states", sealedStates), + ); +} - languages.registerCodeActionsProvider( +/* 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( + 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"; + 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