Skip to content

Commit

Permalink
Web: Support mounting OPFS at arbitrary paths in Playground (#1479)
Browse files Browse the repository at this point in the history
## Motivation for the change, related issues

We're hacking on a Markdown editor, and it can only be useful if there's
a way of editing local Markdown files. This PR provides just that.

## Implementation details

### `startPlaygroundWeb()` now accepts an `onBeforeBlueprint` callback

To mount the markdown files before the Blueprint runs, we added a way to
await user input in the flow. It's an async callback that
`startPlaygroundWeb()` will await before running the Blueprint. It's
used like this:

```ts
startPlaygroundWeb({
	// ... options
	async onBeforeBlueprint() {
		if(!usingDirectoryHandle) return;
		const directoryHandle = await handleFromUserInput;
		await playground.bindOpfs({
			opfs: directoryHandle,
			mountpoint: '/wordpress/wp-content/markdown'
		});
	}
});
```

### Accepting a mountpoint in `playground.bindOpfs()`

It is now possible to pass an arbitrary mountpoint when binding a
DirectoryHandle to Playground's virtual filesystem. For example:

```ts
await playground.bindOpfs({
	opfs: markdownDirectory,
	mountpoint: '/wordpress/wp-content/markdown',
	initialSyncDirection: 'opfs-to-memfs',
};
``` 

Here's the how the `bindOpfs` signature changed:

**Before:**

```ts
async bindOpfs(
	opfs: FileSystemDirectoryHandle,
	onProgress?: SyncProgressCallback
)
```

**After:**

```ts
async bindOpfs(
	options: BindOpfsOptions,
	onProgress?: SyncProgressCallback
)
``` 

You might wonder why is onProgress not a part of `options`. Great
question! That's because the `.bindOpfs` call is done in a top-level
page that embeds `remote.html` via an iframe and the arguments are
serialized and passed by the Comlink.js library. We do have handlers for
serializing functions, but not for serializing functions that are object
properties. This could be improved in the future, but for now onProgress
will remain a separate argument.

### Markdown modal

![CleanShot 2024-06-01 at 12 25
15@2x](https://github.com/WordPress/wordpress-playground/assets/205419/e7f7b378-71fa-426a-a262-52d7edd2e43b)


### Internal changes in Playground website

Part of the state is now managed using redux instead of React context.
There's still some context left to refactor, that would make a great
follow-up PR.

## Testing Instructions (or ideally a Blueprint)

* Go to Playground settings, select storage type device, select an empty
directory, confirm WordPress got copied there without any issues. Then
make some changes in WordPress, reload the page, confirm your changes
are still there.
* Go to the Markdown modal flow at
http://localhost:5400/website-server/?modal=mount-markdown-directory,
select a non-empty directory, confirm it's now mounted by running this
in your devtools and inspecting the resulting list:

```js
await playground.listFiles('/wordpress/wp-content/markdown');
```

---------

Co-authored-by: bgrgicak <[email protected]>
  • Loading branch information
adamziel and bgrgicak authored Jun 1, 2024
1 parent bd9798e commit 4a3ee49
Show file tree
Hide file tree
Showing 30 changed files with 576 additions and 240 deletions.
159 changes: 131 additions & 28 deletions package-lock.json

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

11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@
"private": true,
"dependencies": {
"@preact/signals-react": "1.3.6",
"@reduxjs/toolkit": "2.2.5",
"@types/ini": "4.1.0",
"@types/wicg-file-system-access": "2023.10.5",
"axios": "1.6.1",
"classnames": "^2.3.2",
"comlink": "^4.4.1",
Expand All @@ -65,9 +67,10 @@
"ini": "4.1.2",
"octokit": "3.1.1",
"octokit-plugin-create-pull-request": "5.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.2.25",
"react-dom": "^18.2.25",
"react-modal": "^3.16.1",
"react-redux": "8.1.3",
"react-router-dom": "6.23.1",
"unzipper": "0.10.11",
"vite-plugin-api": "1.0.4",
Expand Down Expand Up @@ -180,8 +183,8 @@
"overrides": {
"nx": "16.9.0",
"rollup": "^3.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.2.25",
"react-dom": "^18.2.25",
"typescript": "5.4.5",
"typedoc": "0.23.27"
},
Expand Down
7 changes: 2 additions & 5 deletions packages/php-wasm/web/src/lib/directory-handle-mount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@ import {
import { Semaphore, joinPaths } from '@php-wasm/util';
import { logger } from '@php-wasm/logger';
import { FilesystemOperation, journalFSEvents } from '@php-wasm/fs-journal';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type * as pleaseLoadTypes from 'wicg-file-system-access';

declare global {
interface FileSystemDirectoryHandle {
values: () => AsyncIterable<
FileSystemDirectoryHandle | FileSystemFileHandle
>;
}
interface FileSystemFileHandle {
move(target: FileSystemDirectoryHandle): Promise<void>;
move(name: string): Promise<void>;
Expand Down
Loading

0 comments on commit 4a3ee49

Please sign in to comment.