Skip to content

Commit

Permalink
Merge pull request #140 from 10play/add-dynamic-height
Browse files Browse the repository at this point in the history
Add dynamic height
  • Loading branch information
GuySerfaty authored Jun 23, 2024
2 parents a913d27 + d510a6a commit 7973a35
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 25 deletions.
118 changes: 96 additions & 22 deletions example/src/Examples/Advanced/editor-web/build/editorHtml.ts

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/RichText/RichText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useKeyboard } from '../utils';
import type { EditorBridge } from '../types';
import { getInjectedJS, getInjectedJSBeforeContentLoad } from './utils';
import { isFabric } from '../utils/misc';
import { CoreEditorActionType } from '../bridges/core';

interface RichTextProps extends WebViewProps {
editor: EditorBridge;
Expand All @@ -36,6 +37,7 @@ const DEV_SERVER_URL = 'http://localhost:3000';
const TOOLBAR_HEIGHT = 44;

export const RichText = ({ editor, ...props }: RichTextProps) => {
const [editorHeight, setEditorHeight] = useState(0);
const [loaded, setLoaded] = useState(isFabric());
const { keyboardHeight: iosKeyboardHeight, isKeyboardUp } = useKeyboard();
const source: WebViewProps['source'] = editor.DEV
Expand All @@ -49,6 +51,9 @@ export const RichText = ({ editor, ...props }: RichTextProps) => {
const { data } = event.nativeEvent;
// Parse the message sent from the editor
const { type, payload } = JSON.parse(data) as EditorMessage;
if (type === CoreEditorActionType.DocumentHeight) {
setEditorHeight(payload);
}
editor.bridgeExtensions?.forEach((e) => {
e.onEditorMessage && e.onEditorMessage({ type, payload }, editor);
});
Expand Down Expand Up @@ -108,6 +113,7 @@ export const RichText = ({ editor, ...props }: RichTextProps) => {
style={[
RichTextStyles.fullScreen,
{ display: loaded ? 'flex' : 'none' },

Check warning on line 115 in src/RichText/RichText.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { display: "loaded ? 'flex' : 'none'" }
{ height: editor.dynamicHeight ? editorHeight : undefined },
editor.theme.webview,
]}
containerStyle={editor.theme.webviewContainer}
Expand Down
2 changes: 2 additions & 0 deletions src/RichText/useEditorBridge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const useEditorBridge = (options?: {
avoidIosKeyboard?: boolean;
customSource?: string;
webviewBaseURL?: string;
dynamicHeight?: boolean;
editable?: boolean;
onChange?: () => void;
DEV?: boolean;
Expand Down Expand Up @@ -127,6 +128,7 @@ export const useEditorBridge = (options?: {
bridgeExtensions,
initialContent: options?.initialContent,
autofocus: options?.autofocus,
dynamicHeight: options?.dynamicHeight,
avoidIosKeyboard: options?.avoidIosKeyboard,
customSource: options?.customSource,
editable,
Expand Down
1 change: 1 addition & 0 deletions src/RichText/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export const getInjectedJSBeforeContentLoad = (editor: EditorBridge) => {
: ''
}
window.editable = ${editor.editable};
window.dynamicHeight = ${editor.dynamicHeight};
`);
};

Expand Down
5 changes: 5 additions & 0 deletions src/bridges/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export enum CoreEditorActionType {
EditorReady = 'editor-ready',
UpdateScrollThresholdAndMargin = 'update-scroll-threshold-and-margin',
ContentUpdate = 'content-update',
DocumentHeight = 'document-height',
SetEditable = 'set-editable',
}

Expand Down Expand Up @@ -135,6 +136,10 @@ export type CoreMessages =
type: CoreEditorActionType.ContentUpdate;
payload: undefined;
}
| {
type: CoreEditorActionType.DocumentHeight;
payload: number;
}
| {
type: CoreEditorActionType.SetEditable;
payload: boolean;
Expand Down
7 changes: 6 additions & 1 deletion src/simpleWebEditor/Tiptap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,10 @@ let tenTapExtensions = TenTapStartKit.filter(
export default function Tiptap() {
const editor = useTenTap({ bridges: tenTapExtensions });

return <EditorContent editor={editor} />;
return (
<EditorContent
editor={editor}
className={window.dynamicHeight ? 'dynamic-height' : undefined}
/>
);
}
11 changes: 9 additions & 2 deletions src/simpleWebEditor/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,24 @@
padding: 0;
}
#root > div:nth-of-type(1) {
overflow: auto;
height: 100%;
position: absolute;
height: 100%;
overflow: auto;
width: 100%;
top: 0;
bottom: 0;
}
#root > div.dynamic-height {
height: unset;
}

#root div .ProseMirror {
height: 100%;
overflow: auto;
}
#root div.dynamic-height .ProseMirror {
height: unset;
}
.ProseMirror:focus {
outline: none;
}
Expand Down
2 changes: 2 additions & 0 deletions src/types/EditorBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface EditorBridge {
webviewBaseURL?: string;
DEV?: boolean;
DEV_SERVER_URL?: string;
dynamicHeight?: boolean;
autofocus: boolean;
focus: (pos?: 'start' | 'end' | 'all' | number | boolean | null) => void;
initialContent?: string;
Expand All @@ -20,6 +21,7 @@ export interface EditorBridge {
_updateEditorState: (state: BridgeState) => void;
_subscribeToEditorStateUpdate: Subscription<BridgeState>;
_onContentUpdate: () => void;
_onContentHeightUpdate: (height: number) => void;
_subscribeToContentUpdate: Subscription<void>;
bridgeExtensions?: BridgeExtension<unknown, unknown, unknown>[];
}
40 changes: 40 additions & 0 deletions src/webEditorUtils/contentHeight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// For some reason on expo, this file is parsed on native, and then we get an error
import { isExpo } from '../utils/misc';

class ContentHeightListener {
public connected = false;
private resizeObserver: ResizeObserver | null = null;
private currentHeight: number | null = null;

public connect(element: Element, cb: (height: number) => void) {
this.connected = true;
this.currentHeight = element.getBoundingClientRect().height;
cb(this.currentHeight);

this.resizeObserver = new ResizeObserver((entries) => {
for (let entry of entries) {
const newHeight = entry.target.getBoundingClientRect().height;
if (this.currentHeight !== newHeight) {
this.currentHeight = newHeight;
cb(newHeight);
}
}
});

this.resizeObserver.observe(element);
}

public disconnect() {
this.resizeObserver?.disconnect();
}

public get height() {
return this.currentHeight;
}
}

// when bundling because "document" does not exist. This is a hack to "shim" focusListener on expo
const shimmedHeightListener = { height: 0, connect: () => {}, connected: true };
export const contentHeightListener = isExpo()
? shimmedHeightListener
: new ContentHeightListener();
15 changes: 15 additions & 0 deletions src/webEditorUtils/useTenTap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import { type BridgeState } from '../types/EditorBridge';
import type BridgeExtension from '../bridges/base';
import { CoreEditorActionType } from '../bridges/core';
import { blueBackgroundPlugin } from '../bridges/HighlightSelection';
import { contentHeightListener } from './contentHeight';
declare global {
interface Window {
initialContent: string;
editable: string;
bridgeExtensionConfigMap: string;
whiteListBridgeExtensions: string[];
dynamicHeight?: boolean;
ReactNativeWebView: { postMessage: (message: string) => void };
}
}
Expand Down Expand Up @@ -128,5 +130,18 @@ export const useTenTap = (options?: useTenTapArgs) => {
};
}, [editor, bridges]);

useEffect(() => {
if (editor && !contentHeightListener.connected && window.dynamicHeight)
contentHeightListener.connect(
document.querySelector('.ProseMirror')!,
(height) => {
sendMessage({
type: CoreEditorActionType.DocumentHeight,
payload: height,
});
}
);
}, [editor]);

return editor;
};
6 changes: 6 additions & 0 deletions website/docs/api/useEditorBridge.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ when true the editor will auto focus
<u>default</u>: `false`<br />
This helps us keep the cursor right above the keyboard when the editor is full-screen and the virtual keyboard hides the bottom portion of the editor.

#### dynamicHeight

`boolean`
<u>default</u>: `false`<br />
when true the editor's webview will keep the same height as the content height

#### theme

`EditorTheme`
Expand Down

0 comments on commit 7973a35

Please sign in to comment.