Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added template web view providers #19

Merged
merged 3 commits into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/extension-template.web-view.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import papi from "papi";
import { useState } from "react";
import { QuickVerseDataProvider } from "extension-types";
import { Button } from "papi-components";

const {
react: {
hooks: { useData, useDataProvider },
components: { Button },
},
logger,
} = papi;
Expand Down
104 changes: 80 additions & 24 deletions lib/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ import extensionTemplateReact from "./extension-template.web-view";
import extensionTemplateReactStyles from "./extension-template.web-view.scss?inline";
// @ts-expect-error ts(1192) this file has no default export; the text is exported by rollup
import extensionTemplateHtml from "./extension-template-html.web-view.ejs";
import type { WebViewContentType } from "shared/data/web-view.model";
import type {
SavedWebViewDefinition,
WebViewContentType,
WebViewDefinition,
} from "shared/data/web-view.model";
import type { UnsubscriberAsync } from "shared/utils/papi-util";
import type { IWebViewProvider } from "shared/models/web-view-provider.model";

const { logger } = papi;

console.log(import.meta.env.PROD);

logger.info("Extension template is importing!");

const unsubscribers = [];

type QuickVerseSetData = string | { text: string; isHeresy: boolean };

class QuickVerseDataProviderEngine
Expand Down Expand Up @@ -129,6 +133,50 @@ class QuickVerseDataProviderEngine
}
}

const htmlWebViewType = "paranext-extension-template.html";

/**
* Simple web view provider that provides sample html web views when papi requests them
*/
const htmlWebViewProvider: IWebViewProvider = {
async getWebView(
savedWebView: SavedWebViewDefinition
): Promise<WebViewDefinition | undefined> {
if (savedWebView.webViewType !== htmlWebViewType)
throw new Error(
`${htmlWebViewType} provider received request to provide a ${savedWebView.webViewType} web view`
);
return {
...savedWebView,
title: "Extension Template HTML",
contentType: "html" as WebViewContentType.HTML,
content: extensionTemplateHtml,
};
},
};

const reactWebViewType = "paranext-extension-template.react";

/**
* Simple web view provider that provides React web views when papi requests them
*/
const reactWebViewProvider: IWebViewProvider = {
async getWebView(
savedWebView: SavedWebViewDefinition
): Promise<WebViewDefinition | undefined> {
if (savedWebView.webViewType !== reactWebViewType)
throw new Error(
`${reactWebViewType} provider received request to provide a ${savedWebView.webViewType} web view`
);
return {
...savedWebView,
title: "Extension Template React",
content: extensionTemplateReact,
styles: extensionTemplateReactStyles,
};
},
};

export async function activate() {
logger.info("Extension template is activating!");

Expand All @@ -137,6 +185,16 @@ export async function activate() {
new QuickVerseDataProviderEngine()
);

const htmlWebViewProviderPromise = papi.webViews.registerWebViewProvider(
htmlWebViewType,
htmlWebViewProvider
);

const reactWebViewProviderPromise = papi.webViews.registerWebViewProvider(
reactWebViewType,
reactWebViewProvider
);

const unsubPromises = [
papi.commands.registerCommand(
"extension-template.do-stuff",
Expand All @@ -146,31 +204,29 @@ export async function activate() {
),
];

papi.webViews.addWebView({
id: 'Extension template WebView React',
content: extensionTemplateReact,
styles: extensionTemplateReactStyles,
});

papi.webViews.addWebView({
id: 'Extension template WebView HTML',
contentType: 'html' as WebViewContentType.HTML,
content: extensionTemplateHtml,
});
// Create webviews or get an existing webview if one already exists for this type
// Note: here, we are using `existingId: '?'` to indicate we do not want to create a new webview
// if one already exists. The webview that already exists could have been created by anyone
// anywhere; it just has to match `webViewType`. See `paranext-core's hello-someone.ts` for an example of keeping
// an existing webview that was specifically created by `paranext-core's hello-someone`.
papi.webViews.getWebView(htmlWebViewType, undefined, { existingId: "?" });
papi.webViews.getWebView(reactWebViewType, undefined, { existingId: "?" });

// For now, let's just make things easy and await the data provider promise at the end so we don't hold everything else up
const quickVerseDataProviderInfo = await quickVerseDataProviderInfoPromise;

return Promise.all(
unsubPromises.map((unsubPromise) => unsubPromise.promise)
).then(() => {
logger.info("Extension template is finished activating!");
return papi.util.aggregateUnsubscriberAsyncs(
unsubPromises
.map((unsubPromise) => unsubPromise.unsubscriber)
.concat([quickVerseDataProviderInfo.dispose])
const htmlWebViewProviderResolved = await htmlWebViewProviderPromise;
const reactWebViewProviderResolved = await reactWebViewProviderPromise;

const combinedUnsubscriber: UnsubscriberAsync =
papi.util.aggregateUnsubscriberAsyncs(
(await Promise.all(unsubPromises)).concat([
quickVerseDataProviderInfo.dispose,
htmlWebViewProviderResolved.dispose,
reactWebViewProviderResolved.dispose,
])
);
});
logger.info("Extension template is finished activating!");
return combinedUnsubscriber;
}

export async function deactivate() {
Expand Down
91 changes: 76 additions & 15 deletions package-lock.json

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

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"lint": "tsc"
},
"dependencies": {
"papi-components": "file:../paranext-core/lib/papi-components",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
Expand All @@ -29,7 +30,7 @@
"glob": "^10.2.2",
"papi-dts": "file:../paranext-core/lib/papi-dts",
"patch-package": "^7.0.0",
"rollup-plugin-import-manager": "^0.6.2",
"rollup-plugin-import-manager": "^0.6.3",
"rollup-plugin-string": "^3.0.0",
"sass": "^1.62.1",
"typescript": "^4.9.3",
Expand Down
6 changes: 5 additions & 1 deletion vite/vite-web-view.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const webViewConfig = defineConfig(async ({ mode }) => {
],
// Since Vite is in library mode `process` is not replaced by default and that won't work in the
// renderer.
define: { 'process.env.NODE_ENV': JSON.stringify(mode) },
define: { "process.env.NODE_ENV": JSON.stringify(mode) },
build: {
// This project is a library as it is being used in Paranext
lib: {
Expand Down Expand Up @@ -75,6 +75,10 @@ const webViewConfig = defineConfig(async ({ mode }) => {
rollupOptions: {
// Do not bundle papi because it will be imported in Paranext
external: paranextProvidedModules,
output: {
// Disable code splitting and chunks. Extension WebViews must be a single file
manualChunks: () => "webView",
},
},
// Bundle the sourcemap into the webview file since it will be injected as a string
// into the main file
Expand Down
4 changes: 4 additions & 0 deletions vite/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ const extensionConfig = defineConfig(async () => {
rollupOptions: {
// Do not bundle papi because it will be imported in Paranext
external: paranextProvidedModules,
output: {
// Disable code splitting and chunks. Extension main must be a single file
manualChunks: () => "main",
},
},
// Generate sourcemaps as separate files since VSCode can load them directly
sourcemap: true,
Expand Down