Skip to content

Commit

Permalink
feat: chang getState and setState methods
Browse files Browse the repository at this point in the history
  • Loading branch information
tomgao365 committed Oct 8, 2024
1 parent cbf2d68 commit b1f38c4
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 312 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ In development mode, inject the same code of [@tomjs/vscode-extension-webview](h
- Simple configuration, focus on business
- Support `esm` and `cjs`
- Support webview `HMR`
- Support `acquireVsCodeApi` of [@types/vscode-webview](https://www.npmjs.com/package/@types/vscode-webview)
- Support [Multi-Page App](https://vitejs.dev/guide/build.html#multi-page-app)
- Supports `vue` and `react` and other [frameworks](https://cn.vitejs.dev/guide/#trying-vite-online) supported by `vite`

Expand Down Expand Up @@ -384,3 +385,11 @@ Open the [examples](./examples) directory, there are `vue` and `react` examples.
- [@tomjs/vscode](https://npmjs.com/package/@tomjs/vscode): Some utilities to simplify the development of [VSCode Extensions](https://marketplace.visualstudio.com/VSCode).
- [@tomjs/vscode-dev](https://npmjs.com/package/@tomjs/vscode-dev): Some development tools to simplify the development of [vscode extensions](https://marketplace.visualstudio.com/VSCode).
- [@tomjs/vscode-webview](https://npmjs.com/package/@tomjs/vscode-webview): Optimize the `postMessage` issue between `webview` page and [vscode extensions](https://marketplace.visualstudio.com/VSCode)

## Important Notes

### v3.0.0

**Breaking Updates:**

- The simulated `acquireVsCodeApi` is consistent with the `acquireVsCodeApi` of [@types/vscode-webview](https://www.npmjs.com/package/@types/vscode-webview), and `sessionStorage.getItem` and `sessionStorage.setItem` are used to implement `getState` and `setState`.
9 changes: 9 additions & 0 deletions README.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- 配置简单,专注业务
- 支持 `esm``cjs`
- 支持 webview `HMR`
- 支持 [@types/vscode-webview](https://www.npmjs.com/package/@types/vscode-webview)`acquireVsCodeApi`
- 支持[多页面应用](https://cn.vitejs.dev/guide/build.html#multi-page-app)
- 支持 `vue``react` 等其他 `vite` 支持的[框架](https://cn.vitejs.dev/guide/#trying-vite-online)

Expand Down Expand Up @@ -387,3 +388,11 @@ pnpm build
- [@tomjs/vscode](https://npmjs.com/package/@tomjs/vscode): 一些实用工具,用于简化 [vscode 扩展](https://marketplace.visualstudio.com/VSCode) 的开发。
- [@tomjs/vscode-dev](https://npmjs.com/package/@tomjs/vscode-dev): 一些开发工具,用于简化 [vscode 扩展](https://marketplace.visualstudio.com/VSCode) 的开发。
- [@tomjs/vscode-webview](https://npmjs.com/package/@tomjs/vscode-webview): 优化 `webview` 页面与 [vscode 扩展](https://marketplace.visualstudio.com/VSCode)`postMessage` 问题

## 重要说明

### v3.0.0

**破坏性更新:**

- 模拟的 `acquireVsCodeApi`[@types/vscode-webview](https://www.npmjs.com/package/@types/vscode-webview)`acquireVsCodeApi` 保持一致,改用 `sessionStorage.getItem``sessionStorage.setItem` 来实现 `getState``setState`
16 changes: 8 additions & 8 deletions examples/react/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@ import { vscode } from './utils/vscode';
import './App.css';

function App() {
function onPostMessage() {
vscode.postMessage({
type: 'hello',
data: 'Hey there partner! 🤠' + message,
});
}

const [message, setMessage] = useState('');
const [state, setState] = useState('');

const onSetState = () => {
vscode.setState(state);
};
const onGetState = () => {
setState(vscode.getState() as string);
setState((vscode.getState() || '') as string);
};

function onPostMessage() {
vscode.postMessage({
type: 'hello',
data: `💬: ${message || 'Empty'}`,
});
}

return (
<main>
<h1>Hello React!</h1>
Expand Down
84 changes: 1 addition & 83 deletions examples/react/src/utils/vscode.ts
Original file line number Diff line number Diff line change
@@ -1,84 +1,2 @@
import type { WebviewApi } from 'vscode-webview';

/**
* A utility wrapper around the acquireVsCodeApi() function, which enables
* message passing and state management between the webview and extension
* contexts.
*
* This utility also enables webview code to be run in a web browser-based
* dev server by using native web browser features that mock the functionality
* enabled by acquireVsCodeApi.
*/
class VSCodeAPIWrapper {
private readonly vsCodeApi: WebviewApi<unknown> | undefined;

constructor() {
console.log(typeof acquireVsCodeApi);
// Check if the acquireVsCodeApi function exists in the current development
// context (i.e. VS Code development window or web browser)
if (typeof acquireVsCodeApi === 'function') {
this.vsCodeApi = acquireVsCodeApi();
}
}

// private init() {
// // TODO 环境变量判断
// }

/**
* Post a message (i.e. send arbitrary data) to the owner of the webview.
*
* @remarks When running webview code inside a web browser, postMessage will instead
* log the given message to the console.
*
* @param message Abitrary data (must be JSON serializable) to send to the extension context.
*/
public postMessage(message: unknown) {
if (this.vsCodeApi) {
this.vsCodeApi.postMessage(message);
} else {
window.parent.postMessage({ type: 'page:message', data: message }, '*');
console.log(message);
}
}

/**
* Get the persistent state stored for this webview.
*
* @remarks When running webview source code inside a web browser, getState will retrieve state
* from local storage (https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
*
* @return The current state or `undefined` if no state has been set.
*/
public getState(): unknown | undefined {
if (this.vsCodeApi) {
return this.vsCodeApi.getState();
} else {
const state = localStorage.getItem('vscodeState');
return state ? JSON.parse(state) : undefined;
}
}

/**
* Set the persistent state stored for this webview.
*
* @remarks When running webview source code inside a web browser, setState will set the given
* state using local storage (https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
*
* @param newState New persisted state. This must be a JSON serializable object. Can be retrieved
* using {@link getState}.
*
* @return The new state.
*/
public setState<T extends unknown | undefined>(newState: T): T {
if (this.vsCodeApi) {
return this.vsCodeApi.setState(newState);
} else {
localStorage.setItem('vscodeState', JSON.stringify(newState));
return newState;
}
}
}

// Exports class singleton to prevent multiple invocations of acquireVsCodeApi.
export const vscode = new VSCodeAPIWrapper();
export const vscode = acquireVsCodeApi<any>();
84 changes: 1 addition & 83 deletions examples/vue-import/src/utils/vscode.ts
Original file line number Diff line number Diff line change
@@ -1,84 +1,2 @@
import type { WebviewApi } from 'vscode-webview';

/**
* A utility wrapper around the acquireVsCodeApi() function, which enables
* message passing and state management between the webview and extension
* contexts.
*
* This utility also enables webview code to be run in a web browser-based
* dev server by using native web browser features that mock the functionality
* enabled by acquireVsCodeApi.
*/
class VSCodeAPIWrapper {
private readonly vsCodeApi: WebviewApi<unknown> | undefined;

constructor() {
console.log(typeof acquireVsCodeApi);
// Check if the acquireVsCodeApi function exists in the current development
// context (i.e. VS Code development window or web browser)
if (typeof acquireVsCodeApi === 'function') {
this.vsCodeApi = acquireVsCodeApi();
}
}

// private init() {
// // TODO 环境变量判断
// }

/**
* Post a message (i.e. send arbitrary data) to the owner of the webview.
*
* @remarks When running webview code inside a web browser, postMessage will instead
* log the given message to the console.
*
* @param message Abitrary data (must be JSON serializable) to send to the extension context.
*/
public postMessage(message: unknown) {
if (this.vsCodeApi) {
this.vsCodeApi.postMessage(message);
} else {
window.parent.postMessage({ type: 'page:message', data: message }, '*');
console.log(message);
}
}

/**
* Get the persistent state stored for this webview.
*
* @remarks When running webview source code inside a web browser, getState will retrieve state
* from local storage (https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
*
* @return The current state or `undefined` if no state has been set.
*/
public getState(): unknown | undefined {
if (this.vsCodeApi) {
return this.vsCodeApi.getState();
} else {
const state = localStorage.getItem('vscodeState');
return state ? JSON.parse(state) : undefined;
}
}

/**
* Set the persistent state stored for this webview.
*
* @remarks When running webview source code inside a web browser, setState will set the given
* state using local storage (https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
*
* @param newState New persisted state. This must be a JSON serializable object. Can be retrieved
* using {@link getState}.
*
* @return The new state.
*/
public setState<T extends unknown | undefined>(newState: T): T {
if (this.vsCodeApi) {
return this.vsCodeApi.setState(newState);
} else {
localStorage.setItem('vscodeState', JSON.stringify(newState));
return newState;
}
}
}

// Exports class singleton to prevent multiple invocations of acquireVsCodeApi.
export const vscode = new VSCodeAPIWrapper();
export const vscode = acquireVsCodeApi<any>();
3 changes: 3 additions & 0 deletions examples/vue/extension/views/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ export class WebviewHelper {
console.log(`type: ${type}`);
switch (type) {
case 'hello':
case 'hello2':
case 'hello3':
window.showInformationMessage(data);
webview.postMessage({ type, data: Date.now() });
return;
}
},
Expand Down
46 changes: 32 additions & 14 deletions examples/vue/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,35 +1,53 @@
<script setup lang="ts">
import { ref } from 'vue';
import { vscodeWebview } from '@tomjs/vscode-webview';
import { allComponents, provideVSCodeDesignSystem } from '@vscode/webview-ui-toolkit';
import { vscode } from './utils';
import { vscodeApi } from './utils';
provideVSCodeDesignSystem().register(allComponents);
function onPostMessage() {
vscodeWebview.postMessage('hello', 'Hey there partner! 🤠');
}
vscodeWebview.on('hello', data => {
console.log('on message:', data);
});
const message = ref('');
const state = ref('');
const onSetState = () => {
vscode.setState(state.value);
vscodeApi.setState(state.value);
};
const onGetState = async () => {
state.value = (await vscode.getState()) as string;
const onGetState = () => {
state.value = vscodeApi.getState() || '';
};
function onPostMessage() {
vscodeApi.postMessage({
type: 'hello',
data: `💬: ${message.value || 'Empty'}`,
});
setTimeout(() => {
vscodeApi.post('hello3', `⛅: ${message.value || 'Empty'}`);
}, 100);
}
const receive = ref('');
function onPostAndReceive() {
vscodeApi.postAndReceive('hello2', `😀: ${message.value || 'Empty'}`).then((data: any) => {
console.log('data', data);
receive.value = data;
});
}
vscodeApi.on('hello3', (data: any) => {
console.log('watch [hello3]: ', data);
});
</script>

<template>
<main>
<h1>Hello Vue!</h1>
<vscode-button @click="onPostMessage">Test VSCode Message</vscode-button>
<vscode-button @click="onPostMessage">Post Message</vscode-button>
<div style="margin-top: 8px">
<vscode-button @click="onPostAndReceive"> Post Message And Receive </vscode-button>
<span v-if="receive" style="margin-left: 8px">{{ receive }}</span>
</div>
<div>
<vscode-text-field :value="message" @input="e => (message = e.target.value)">
Please enter a message
Expand Down
Loading

0 comments on commit b1f38c4

Please sign in to comment.