Skip to content

Commit 0d58f60

Browse files
RedditbaraObsidianSnoo
Redditbara
authored andcommitted
Project import generated by Copybara.
GitOrigin-RevId: 6a2c027f8df33415e299545ba782158690b6768e
1 parent cbd6e17 commit 0d58f60

34 files changed

+241
-138
lines changed

devvit-docs/docs/api/public-api/README.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -1784,11 +1784,12 @@ event handlers, a Form's `onSubmit` handler, and Menu items.
17841784

17851785
#### Type declaration
17861786

1787-
| Name | Type |
1788-
| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1789-
| `navigateTo` | (`url`: `string`) => `void`(`subreddit`: `Subreddit`) => `void`(`post`: `Post`) => `void`(`comment`: `Comment`) => `void`(`user`: `User`) => `void`(`urlOrThing`: `string` \| `User` \| `Subreddit` \| `Post` \| `Comment`) => `void` |
1790-
| `showForm` | (`formKey`: [`FormKey`](README.md#formkey), `data?`: [`JSONObject`](README.md#jsonobject)) => `void` |
1791-
| `showToast` | (`text`: `string`) => `void`(`toast`: [`Toast`](README.md#toast)) => `void` |
1787+
| Name | Type | Description |
1788+
| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------- |
1789+
| `webView` | `WebViewUIClient` | Interact with WebView blocks |
1790+
| `navigateTo` | (`url`: `string`) => `void`(`subreddit`: `Subreddit`) => `void`(`post`: `Post`) => `void`(`comment`: `Comment`) => `void`(`user`: `User`) => `void`(`urlOrThing`: `string` \| `User` \| `Subreddit` \| `Post` \| `Comment`) => `void` | Navigate to a URL |
1791+
| `showForm` | (`formKey`: [`FormKey`](README.md#formkey), `data?`: [`JSONObject`](README.md#jsonobject)) => `void` | Open a form in a modal |
1792+
| `showToast` | (`text`: `string`) => `void`(`toast`: [`Toast`](README.md#toast)) => `void` | Show a message in a toast. |
17921793

17931794
---
17941795

devvit-docs/docs/api/public-api/modules/Devvit.Blocks.md

+11-5
Original file line numberDiff line numberDiff line change
@@ -282,17 +282,23 @@ large = 24px;
282282

283283
### <a id="onwebvieweventhandler" name="onwebvieweventhandler"></a> OnWebViewEventHandler
284284

285-
Ƭ **OnWebViewEventHandler**: (`message`: [`JSONObject`](../README.md#jsonobject)) => `void` \| `Promise`\<`void`\>
285+
Ƭ **OnWebViewEventHandler**: \<T\>(`message`: `T`) => `void` \| `Promise`\<`void`\>
286286

287287
#### Type declaration
288288

289-
▸ (`message`): `void` \| `Promise`\<`void`\>
289+
\<`T`\>(`message`): `void` \| `Promise`\<`void`\>
290+
291+
##### Type parameters
292+
293+
| Name | Type |
294+
| :--- | :-------------------------------------------- |
295+
| `T` | extends [`JSONValue`](../README.md#jsonvalue) |
290296

291297
##### Parameters
292298

293-
| Name | Type |
294-
| :-------- | :-------------------------------------- |
295-
| `message` | [`JSONObject`](../README.md#jsonobject) |
299+
| Name | Type |
300+
| :-------- | :--- |
301+
| `message` | `T` |
296302

297303
##### Returns
298304

packages/apps/webview-example/package.json packages/apps/web-view-example/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"private": true,
3-
"name": "webview-example",
3+
"name": "web-view-example",
44
"version": "0.11.3-dev",
55
"license": "BSD-3-Clause",
66
"type": "module",

packages/cli/src/templates/webviews/src/createPost.tsx packages/apps/web-view-example/src/createPost.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Devvit.configure({
55
});
66

77
Devvit.addMenuItem({
8-
label: 'Create Webview Example Post',
8+
label: 'Create WebView Example Post',
99
location: 'subreddit',
1010
onPress: async (_event, context) => {
1111
const { reddit, ui } = context;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import './createPost.js';
2+
3+
import { Devvit, type JSONValue, useState } from '@devvit/public-api';
4+
5+
type MyMessageType = {
6+
foo: string;
7+
};
8+
9+
Devvit.addCustomPostType({
10+
name: 'WebView Example',
11+
height: 'tall',
12+
render: (context) => {
13+
const [webViewState, setWebViewState] = useState({
14+
lastUpdate: 0,
15+
});
16+
17+
const onMessage = (msg: JSONValue): void => {
18+
if (msg) {
19+
console.log(msg);
20+
const newState = { ...webViewState, lastUpdate: Date.now() };
21+
setWebViewState(newState);
22+
}
23+
};
24+
25+
const sendPing = () => context.ui.webView.postMessage('myWebView', 'ping');
26+
const sendMessage = () =>
27+
context.ui.webView.postMessage<MyMessageType>('myWebView', { foo: 'bar' });
28+
29+
return (
30+
<vstack grow padding="small">
31+
<text>WebView Content:</text>
32+
<vstack border="thick" borderColor="black" gap="small" grow>
33+
<webview id="myWebView" url="page.html" state={webViewState} onMessage={onMessage} grow />
34+
<button onPress={sendPing}>Send Ping</button>
35+
<button onPress={sendMessage}>Send Message</button>
36+
</vstack>
37+
<vstack grow padding="small">
38+
<text size="small" alignment="middle center">
39+
Your WebView app is working.{' '}
40+
</text>
41+
<text size="small" alignment="middle center">
42+
If you can't see the content of page.html, you likely need to get your app allow-listed
43+
for the webview feature.
44+
</text>
45+
<text size="small" alignment="middle center">
46+
Get in touch with Reddit admins via Discord to allow-list your app.{' '}
47+
</text>
48+
</vstack>
49+
</vstack>
50+
);
51+
},
52+
});
53+
54+
export default Devvit;

packages/apps/webview-example/webroot/page.html packages/apps/web-view-example/webroot/page.html

+3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
</head>
88
<body>
99
<button>Ping</button>
10+
<div id="stateTimestamp"></div>
1011
<pre id="stateOutput"></pre>
12+
<div id="messageTimestamp"></div>
13+
<pre id="messageOutput"></pre>
1114
<script type="application/javascript" src="script.js"></script>
1215
</body>
1316
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
class App {
2+
constructor() {
3+
this.state = {};
4+
5+
const stateOutput = document.querySelector('#stateOutput');
6+
const stateTimestamp = document.querySelector('#stateTimestamp');
7+
const messageOutput = document.querySelector('#messageOutput');
8+
const messageTimestamp = document.querySelector('#messageTimestamp');
9+
10+
window.addEventListener('message', (ev) => {
11+
const { type, data } = ev.data;
12+
13+
if (type === 'devvit-message') {
14+
const { message } = data;
15+
messageOutput.textContent = JSON.stringify(message, undefined, 2);
16+
messageTimestamp.textContent = String(Date.now());
17+
}
18+
if (type === 'devvit-state') {
19+
const { state } = data;
20+
stateOutput.textContent = JSON.stringify(state, undefined, 2);
21+
stateTimestamp.textContent = String(Date.now());
22+
}
23+
});
24+
25+
const pingButton = document.querySelector('button');
26+
pingButton.addEventListener('click', () => {
27+
window.parent?.postMessage({ type: 'ping' }, '*');
28+
});
29+
}
30+
}
31+
32+
new App();

packages/apps/webview-example/src/main.tsx

-43
This file was deleted.

packages/apps/webview-example/webroot/script.js

-21
This file was deleted.

packages/cli/src/commands/playtest.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
import type { Bundle } from '@devvit/protos/types/devvit/plugin/buildpack/buildpack_common.js';
99
import { Severity } from '@devvit/protos/types/devvit/plugin/logger/logger.js';
1010
import { RemoteLogType } from '@devvit/protos/types/devvit/remote_logger/remote_logger.js';
11-
import { ASSET_DIRNAME, WEBVIEW_ASSET_DIRNAME } from '@devvit/shared-types/Assets.js';
11+
import { ASSET_DIRNAME, WEB_VIEW_ASSET_DIRNAME } from '@devvit/shared-types/Assets.js';
1212
import {
1313
ACTOR_SRC_DIR,
1414
ACTOR_SRC_PRIMARY_NAME,
@@ -210,7 +210,7 @@ export default class Playtest extends Upload {
210210
);
211211

212212
const assetDir = path.join(this.projectRoot, ASSET_DIRNAME);
213-
const webviewAssetDir = path.join(this.projectRoot, WEBVIEW_ASSET_DIRNAME);
213+
const webViewAssetDir = path.join(this.projectRoot, WEB_VIEW_ASSET_DIRNAME);
214214
const productsJSON = path.join(this.projectRoot, ACTOR_SRC_DIR, PRODUCTS_JSON_FILE);
215215

216216
const watchSrc = this.#bundler.watch(this.projectRoot, {
@@ -219,7 +219,7 @@ export default class Playtest extends Upload {
219219
version: projectConfig.version,
220220
});
221221

222-
const assetPaths = [assetDir, webviewAssetDir, productsJSON];
222+
const assetPaths = [assetDir, webViewAssetDir, productsJSON];
223223
this.#watchAssets = chokidar.watch(assetPaths, { ignoreInitial: true });
224224

225225
this.#watchAssets.on('all', () => {

packages/cli/src/commands/upload.ts

+11-11
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
MAX_ASSET_GIF_SIZE,
2525
MAX_ASSET_NON_GIF_SIZE,
2626
prettyPrintSize,
27-
WEBVIEW_ASSET_DIRNAME,
27+
WEB_VIEW_ASSET_DIRNAME,
2828
} from '@devvit/shared-types/Assets.js';
2929
import {
3030
ACTOR_SRC_PRIMARY_NAME,
@@ -561,10 +561,10 @@ export default class Upload extends ProjectCommand {
561561
webViewAssetMap?: AssetMap;
562562
}> {
563563
const regularAssets = await this.#getAssets(ASSET_DIRNAME, ALLOWED_ASSET_EXTENSIONS);
564-
let webViewAssets = await this.#getAssets(WEBVIEW_ASSET_DIRNAME, [], true);
564+
let webViewAssets = await this.#getAssets(WEB_VIEW_ASSET_DIRNAME, [], true);
565565

566566
if (!isWebViewEnabled && webViewAssets.length > 0) {
567-
ux.warn('WebView is not enabled for this app. Skipping webview assets.');
567+
ux.warn('WebView is not enabled for this app. Skipping WebView assets.');
568568
webViewAssets = [];
569569
}
570570

@@ -591,7 +591,7 @@ export default class Upload extends ProjectCommand {
591591

592592
// regular assets go to Media Service
593593
const assetMap = await this.#processRegularAssets(regularAssets);
594-
// webroot assets go to webview storage
594+
// webroot assets go to WebView storage
595595
const webViewAssetMap = await this.#processWebViewAssets(webViewAssets);
596596

597597
return { assetMap, webViewAssetMap };
@@ -600,7 +600,7 @@ export default class Upload extends ProjectCommand {
600600
async #getAssets(
601601
folder: string,
602602
allowedExtensions: string[] = [],
603-
webviewAssets: boolean = false
603+
webViewAssets: boolean = false
604604
): Promise<MediaSignatureWithContents[]> {
605605
if (!(await dirExists(path.join(this.projectRoot, folder)))) {
606606
// Return early if there isn't an assets directory
@@ -633,7 +633,7 @@ export default class Upload extends ProjectCommand {
633633
filePath: filename,
634634
size,
635635
hash,
636-
isWebviewAsset: webviewAssets,
636+
isWebviewAsset: webViewAssets,
637637
contents,
638638
};
639639
})
@@ -688,13 +688,13 @@ export default class Upload extends ProjectCommand {
688688
return {};
689689
}
690690

691-
ux.action.start(`Checking for new webview assets to upload...`);
691+
ux.action.start(`Checking for new WebView assets to upload...`);
692692

693693
const assetMap = await this.#uploadNewAssets(assets, true);
694694

695-
ux.action.stop(`Found ${assets.length} new webview asset${assets.length === 1 ? '' : 's'}.`);
695+
ux.action.stop(`Found ${assets.length} new WebView asset${assets.length === 1 ? '' : 's'}.`);
696696

697-
// only return the html files for the webview assets
697+
// only return the html files for the WebView assets
698698
return Object.keys(assetMap).reduce<AssetMap>((map, assetPath) => {
699699
if (assetPath.match(/\.htm(l)?$/)) {
700700
map[assetPath] = assetMap[assetPath];
@@ -707,7 +707,7 @@ export default class Upload extends ProjectCommand {
707707
assets: MediaSignatureWithContents[],
708708
webViewAsset: boolean = false
709709
): Promise<AssetMap> {
710-
const webViewMsg = webViewAsset ? 'webview ' : '';
710+
const webViewMsg = webViewAsset ? 'WebView ' : '';
711711

712712
const config = await this.getProjectConfig();
713713
const { statuses } = await this.appClient.CheckIfMediaExists({
@@ -778,7 +778,7 @@ export default class Upload extends ProjectCommand {
778778
const error = err as Error;
779779
const msg = `Failed to upload ${webViewMsg}assets. (${error.message})`;
780780
if (webViewAsset) {
781-
// don't fail on webview uploads in case we just don't have the feature enabled
781+
// don't fail on WebView uploads in case we just don't have the feature enabled
782782
ux.action.stop(msg);
783783
return {};
784784
} else {

packages/cli/src/templates/webviews/package.json packages/cli/src/templates/web-views/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"private": true,
3-
"name": "webview-template",
3+
"name": "web-view-template",
44
"version": "0.11.1",
55
"license": "BSD-3-Clause",
66
"type": "module",

packages/cli/src/templates/webviews/src/main.tsx packages/cli/src/templates/web-views/src/main.tsx

+6-11
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,22 @@
11
import './createPost.js';
22

3-
import { Devvit, type JSONObject, useState } from '@devvit/public-api';
3+
import { Devvit, type JSONValue } from '@devvit/public-api';
44

55
Devvit.addCustomPostType({
66
name: 'Webview Example',
77
height: 'tall',
8-
render: () => {
9-
const [webviewState, setWebviewState] = useState({
10-
lastUpdate: 0,
11-
});
12-
13-
const onMessage = (msg: JSONObject): void => {
14-
if (msg.type === 'ping') {
15-
const newState = { ...webviewState, lastUpdate: Date.now() };
16-
setWebviewState(newState);
8+
render: (context) => {
9+
const onMessage = (msg: JSONValue): void => {
10+
if (msg === 'ping') {
11+
context.ui.webView.postMessage('myWebView', 'pong');
1712
}
1813
};
1914

2015
return (
2116
<vstack grow padding="small">
2217
<text>WebView Content:</text>
2318
<vstack border="thick" borderColor="black" grow>
24-
<webview url="page.html" state={webviewState} onMessage={onMessage} grow />
19+
<webview id="myWebView" url="page.html" onMessage={onMessage} grow />
2520
</vstack>
2621
<vstack grow padding="small">
2722
<text size="small" alignment="middle center">
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
22
"extends": "@devvit/public-api/devvit.tsconfig.json"
3-
}
3+
}

packages/cli/src/templates/webviews/webroot/page.html packages/cli/src/templates/web-views/webroot/page.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</head>
99
<body>
1010
<button>Ping</button>
11-
<pre id="stateOutput"></pre>
11+
<pre id="messageOutput"></pre>
1212
<script type="application/javascript" src="script.js"></script>
1313
</body>
14-
</html>
14+
</html>

0 commit comments

Comments
 (0)