Skip to content

Commit

Permalink
Try bicep message (#1336)
Browse files Browse the repository at this point in the history
* Show generic Bicep message

* work

* don't show if bicep extension installed

* lint

Co-authored-by: Stephen Weatherford <[email protected]>
  • Loading branch information
StephenWeatherford and Stephen Weatherford authored Jul 16, 2021
1 parent bbb56c1 commit 90fcd20
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 7 deletions.
4 changes: 2 additions & 2 deletions .azure-pipelines/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ jobs:
steps:
- template: common/build.yml
#- template: common/test-without-langserver.yml
- template: common/lint.yml
#- template: common/lint.yml
- template: common/test.yml
- template: common/publish-logs.yml

Expand All @@ -26,6 +26,6 @@ jobs:
steps:
- template: common/build.yml
#- template: common/test-without-langserver.yml
- template: common/lint.yml
#- template: common/lint.yml
- template: common/test.yml
- template: common/publish-logs.yml
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 19 additions & 2 deletions src/AzureRMTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { KnownContexts } from './snippets/KnownContexts';
import { showInsertionContext } from "./snippets/showInsertionContext";
import { SnippetManager } from "./snippets/SnippetManager";
import { survey } from "./survey";
import { TimedMessage } from './TimedMessage';
import { CachedPromise } from "./util/CachedPromise";
import { escapeNonPaths } from "./util/escapeNonPaths";
import { expectTemplateDocument } from "./util/expectDocument";
Expand Down Expand Up @@ -147,6 +148,12 @@ export class AzureRMTools implements IProvideOpenedDocuments {
private _mapping: DeploymentFileMapping = ext.deploymentFileMapping.value;
private _codeLensChangedEmitter: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();
private _linkedTemplateDocProviderChangedEmitter: vscode.EventEmitter<vscode.Uri> = new vscode.EventEmitter<vscode.Uri>();
private _bicepMessage: TimedMessage = new TimedMessage(
globalStateKeys.messages.bicepMessagePostponedUntilTime,
"debugBicepMessage",
"Try Azure Bicep, the next generation of ARM templates, in VS Code",
parseUri("https://aka.ms/bicep-install")
);

// More information can be found about this definition at https://code.visualstudio.com/docs/extensionAPI/vscode-api#DecorationRenderOptions
// Several of these properties are CSS properties. More information about those can be found at https://www.w3.org/wiki/CSS/Properties
Expand Down Expand Up @@ -371,6 +378,12 @@ export class AzureRMTools implements IProvideOpenedDocuments {
const activeDocument = activeEditor.document;
this.updateOpenedDocument(activeDocument);
}

// If the bicep extension is installed, don't ever show the "try bicep" message
if (vscode.extensions.getExtension('ms-azuretools.vscode-bicep')) {
// tslint:disable-next-line: no-floating-promises
this._bicepMessage.neverShowAgain();
}
}
public setStaticDocument(documentOrUri: vscode.Uri, content: string): void {
throw new Error("Method not implemented.");
Expand Down Expand Up @@ -546,7 +559,7 @@ export class AzureRMTools implements IProvideOpenedDocuments {
this.ensureDeploymentDocumentEventsHookedUp();

this.setOpenedDeploymentDocument(documentUri, deploymentTemplate);
survey.registerActiveUse();
this.registerActiveUse();

if (isNewlyOpened) {
// A deployment template has been opened (as opposed to having been tabbed to)
Expand Down Expand Up @@ -599,7 +612,7 @@ export class AzureRMTools implements IProvideOpenedDocuments {
if (treatAsDeploymentParameters) {
this.ensureDeploymentDocumentEventsHookedUp();
this.setOpenedDeploymentDocument(documentUri, deploymentParameters);
survey.registerActiveUse();
this.registerActiveUse();

// tslint:disable-next-line: no-floating-promises
this.reportDeploymentParametersErrorsInBackground(textDocument, deploymentParameters).then(async (errorsWarnings) => {
Expand Down Expand Up @@ -1896,4 +1909,8 @@ export class AzureRMTools implements IProvideOpenedDocuments {
this._codeLensChangedEmitter.fire();
}

private registerActiveUse(): void {
survey.registerActiveUse();
this._bicepMessage.registerActiveUse();
}
}
102 changes: 102 additions & 0 deletions src/TimedMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// ----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------

import { commands, MessageItem, Uri, window } from 'vscode';
import { callWithTelemetryAndErrorHandling, IActionContext } from "vscode-azureextensionui";
import { ext } from "./extensionVariables";
import { assert } from './fixed_assert';
import { minutesToMs, weeksToMs } from "./util/time";

interface ISettings {
delayBetweenAttempts: number;
}

const defaultSettings: ISettings = {
delayBetweenAttempts: weeksToMs(1),
};
const debugSettings: ISettings = {
delayBetweenAttempts: minutesToMs(1),
};

export class TimedMessage {
private _settings: ISettings = defaultSettings;
private _alreadyCheckedThisSession: boolean = false;

public constructor(
private _postponeUntilTimeKey: string,
private _debugSettingKey: string,
private _message: string,
private _learnMoreUri: Uri
) {
}

/**
* Called whenever the user is interacting with the extension (thus gets called a lot)
*/
public registerActiveUse(): void {
if (this._alreadyCheckedThisSession) {
return;
}
this._alreadyCheckedThisSession = true;

// Don't wait
// tslint:disable-next-line: no-floating-promises
callWithTelemetryAndErrorHandling("considerShowingMessage", async (context: IActionContext) => {
context.errorHandling.suppressDisplay = true;
context.telemetry.properties.message = this._message;

await this.checkForDebugMode();

const postponeUntilTime: number = ext.context.globalState.get<number>(this._postponeUntilTimeKey) ?? 0;
if (postponeUntilTime < 0) {
// This means never show again
context.telemetry.properties.status = 'NeverShowAgain';
return;
} else if (Date.now() < postponeUntilTime) {
context.telemetry.properties.status = "TooEarly";
return;
} else if (postponeUntilTime === 0) {
// First time - set up initial delay
await this.postpone();
context.telemetry.properties.status = "FirstDelay";
return;
}

// Time to show message

// In case the user never responds, go ahead and set up postponement until next delay
await this.postpone();

const neverAskAgain: MessageItem = { title: "Never ask again" };
const moreInfo: MessageItem = { title: "More Info" };

const response = await window.showInformationMessage(this._message, moreInfo, neverAskAgain) ?? neverAskAgain;
context.telemetry.properties.response = String(response.title);

// No matter the response, neve show again
await this.neverShowAgain();

if (response === moreInfo) {
await commands.executeCommand('vscode.open', this._learnMoreUri);
} else {
assert(response === neverAskAgain);
}
});
}

private async checkForDebugMode(): Promise<void> {
if (ext.configuration.get<boolean>(this._debugSettingKey)) {
this._settings = debugSettings;
}
}

public async neverShowAgain(): Promise<void> {
this._alreadyCheckedThisSession = true;
await ext.context.globalState.update(this._postponeUntilTimeKey, -1);
}

private async postpone(): Promise<void> {
await ext.context.globalState.update(this._postponeUntilTimeKey, Date.now() + this._settings.delayBetweenAttempts);
}
}
4 changes: 4 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ export namespace globalStateKeys {
export const neverShowSurvey = 'neverShowSurvey';
export const surveyPostponedUntilTime = 'surveyPostponedUntilTime';
}

export namespace messages {
export const bicepMessagePostponedUntilTime = 'bicepMessagePostponedUntilTime';
}
}

// For testing: We create a diagnostic with this message during testing to indicate when all (expression) diagnostics have been calculated
Expand Down
6 changes: 3 additions & 3 deletions src/survey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------

import { commands, MessageItem, window, workspace } from 'vscode';
import { commands, MessageItem, window } from 'vscode';
import { callWithTelemetryAndErrorHandling, IActionContext } from "vscode-azureextensionui";
import { configPrefix, globalStateKeys } from './constants';
import { globalStateKeys } from './constants';
import { ext } from "./extensionVariables";
import { assert } from './fixed_assert';
import { httpGet } from "./util/httpGet";
Expand Down Expand Up @@ -126,7 +126,7 @@ export namespace survey {

async function checkForDebugMode(context: IActionContext): Promise<void> {
if (!isDebugMode) {
if (workspace.getConfiguration(configPrefix).get<boolean>('debugSurvey')) {
if (ext.configuration.get<boolean>('debugSurvey')) {
isDebugMode = true;
surveyConstants = debugSurveyConstants;

Expand Down
1 change: 1 addition & 0 deletions src/vscodeIntegration/resetGlobalState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export async function resetGlobalState(actionContext: IActionContext): Promise<v
ext.context.globalState.update(globalStateKeys.dontAskAboutParameterFiles, undefined);
ext.context.globalState.update(globalStateKeys.survey.neverShowSurvey, undefined);
ext.context.globalState.update(globalStateKeys.survey.surveyPostponedUntilTime, undefined);
ext.context.globalState.update(globalStateKeys.messages.bicepMessagePostponedUntilTime, undefined);

const reload = "Reload Now";
if (reload === await window.showInformationMessage(`Global state for ${extensionName} has been reset.`, reload)) {
Expand Down

0 comments on commit 90fcd20

Please sign in to comment.