Skip to content

Commit fcc0f94

Browse files
committed
attempt to fix mobile keyboard popup
1 parent 6b7d8c8 commit fcc0f94

4 files changed

Lines changed: 64 additions & 27 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"license": "MIT",
2525
"dependencies": {
2626
"@popperjs/core": "^2.11.8",
27-
"@zsviczian/excalidraw": "0.18.0-45",
27+
"@zsviczian/excalidraw": "0.18.0-46",
2828
"chroma-js": "^3.1.2",
2929
"clsx": "^2.0.0",
3030
"@zsviczian/colormaster": "^1.2.2",

src/core/main.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ import { ScriptEngine } from "../shared/Scripts";
6666
import { hoverEvent, initializeMarkdownPostProcessor, markdownPostProcessor, legacyExcalidrawPopoverObserver } from "./managers/MarkdownPostProcessor";
6767
import { FieldSuggester } from "../shared/Suggesters/FieldSuggester";
6868
import { ReleaseNotes } from "../shared/Dialogs/ReleaseNotes";
69-
import { Packages } from "../types/types";
69+
import { DeviceType, Packages } from "../types/types";
7070
import { PreviewImageType } from "../types/utilTypes";
7171
import { emulateCTRLClickForLinks, linkClickModifierType, PaneTarget } from "../utils/modifierkeyHelper";
7272
import { imageCache } from "../shared/ImageCache";
@@ -1482,4 +1482,8 @@ export default class ExcalidrawPlugin extends Plugin {
14821482
public getLabel(key: keyof typeof en): string {
14831483
return t(key);
14841484
}
1485+
1486+
public getObsidianDevice(): DeviceType {
1487+
return DEVICE;
1488+
}
14851489
}

src/shared/Dialogs/Messages.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ I build this plugin in my free time, as a labor of love. Curious about the philo
2626
## Fixed
2727
- side panel does not attach correctly when library is pinned [#2510](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2510)
2828
- Fixed print area when using marker frames and printing Slideshow to PDF
29-
- The "Invert Colors" script and ExcalidrawAutomate bugs that resulted in broken colors and Excalidarw crashes in some cases after color inversion.
29+
- The "Invert Colors" script and ExcalidrawAutomate bugs that resulted in broken colors and Excalidraw crashes in some cases after color inversion.
3030
- Fixed duplicated PDF elements after copy-pasting from scene to scene.
31+
- Resolved the large gap at the top on iOS devices. As it turns out, Apple adds additional padding automatically to avoid collision with the notch.
32+
- Fixed the positioning of the "Canvas and Shape Properties" window.
3133
`,
3234
"2.16.1":`
3335
## Fixed

src/view/ExcalidrawView.ts

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,13 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
335335
private obsidianMenu: ObsidianMenu;
336336
private embeddableMenu: EmbeddableMenu;
337337
private destroyers: Function[] = [];
338+
private contentSizeMap = new WeakMap<Element, number>();
339+
private lastContentResizeDeltaHeight: number;
340+
private resizeBatchTimer: number = null;
341+
private resizeBatchStartHeight = 0;
342+
private lastAggregatedDh = 0;
343+
private lastClientElHeight = 0;
344+
private oldKeyboardScroll:number = null;
338345

339346
//https://stackoverflow.com/questions/27132796/is-there-any-javascript-event-fired-when-the-on-screen-keyboard-on-mobile-safari
340347
private isEditingTextResetTimer: number = null;
@@ -1655,7 +1662,18 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
16551662
this.handleLinkClick(ev),
16561663
);
16571664

1658-
this.registerDomEvent(this.ownerWindow, "resize", this.onExcalidrawResize.bind(this));
1665+
const ro = new ResizeObserver((entries) => {
1666+
for (const entry of entries) {
1667+
const { height } = entry.contentRect;
1668+
const prevHeight = this.contentSizeMap.get(entry.target);
1669+
const dh = prevHeight ? height - prevHeight : 0;
1670+
this.contentSizeMap.set(entry.target, height);
1671+
this.lastContentResizeDeltaHeight = dh;
1672+
this.scheduleBatchedResize(entry);
1673+
}
1674+
});
1675+
ro.observe(this.contentEl);
1676+
this.destroyers.push(() => ro.disconnect());
16591677

16601678
this.app.workspace.onLayoutReady(async () => {
16611679
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.onload,`ExcalidrawView.onload > app.workspace.onLayoutReady, file:${this.file?.name}, isActiveLeaf:${this?.app?.workspace?.activeLeaf === this.leaf}, is activeExcalidrawView set:${Boolean(this?.plugin?.activeExcalidrawView)}`);
@@ -5463,7 +5481,30 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
54635481
return this.obsidianMenu?.renderButton (isMobile, appState);
54645482
}
54655483

5466-
private onExcalidrawResize () {
5484+
private scheduleBatchedResize(entry: ResizeObserverEntry) {
5485+
if (!this.lastClientElHeight) this.lastClientElHeight = this.contentEl.clientHeight;
5486+
5487+
if (!this.resizeBatchTimer) {
5488+
const prev = this.contentSizeMap.get(entry.target);
5489+
this.resizeBatchStartHeight = prev ?? entry.contentRect.height;
5490+
}
5491+
const curH = entry.contentRect.height;
5492+
this.lastAggregatedDh = curH - this.resizeBatchStartHeight;
5493+
5494+
if (this.resizeBatchTimer) window.clearTimeout(this.resizeBatchTimer);
5495+
this.resizeBatchTimer = window.setTimeout(() => {
5496+
const dh = this.lastAggregatedDh;
5497+
const heightNow = this.contentEl.clientHeight ?? 0;
5498+
this.lastClientElHeight = heightNow;
5499+
this.resizeBatchTimer = null;
5500+
this.onExcalidrawResize(dh);
5501+
}, 700);
5502+
}
5503+
5504+
private onExcalidrawResize(dhArg?: number) {
5505+
const dh = typeof dhArg === "number" ? dhArg : this.lastContentResizeDeltaHeight;
5506+
console.log(dh, "(batched)");
5507+
54675508
try {
54685509
const api = this.excalidrawAPI as ExcalidrawImperativeAPI;
54695510
if(!api) return;
@@ -5489,29 +5530,19 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
54895530
const isKeyboardBackEvent:Boolean = (this.semaphores.isEditingText || isEventOnSameElement) && !isKeyboardOutEvent;
54905531
this.editingTextElementId = isKeyboardOutEvent ? st.editingTextElement.id : null;
54915532
if(isKeyboardOutEvent) {
5492-
const appToolHeight = (this.contentEl.querySelector(".Island.App-toolbar") as HTMLElement)?.clientHeight ?? 0;
5493-
const editingElViewY = sceneCoordsToViewportCoords({sceneX:0, sceneY:st.editingTextElement.y}, st).y;
5494-
const scrollViewY = sceneCoordsToViewportCoords({sceneX:0, sceneY:-st.scrollY}, st).y;
5495-
const delta = editingElViewY - scrollViewY;
5496-
const isElementAboveKeyboard = height > (delta + appToolHeight*2)
5497-
const excalidrawWrapper = this.excalidrawWrapperRef.current;
5498-
//console.log({isElementAboveKeyboard});
5499-
if(excalidrawWrapper && !isElementAboveKeyboard) {
5500-
excalidrawWrapper.style.top = `${-(st.height - height)}px`;
5501-
excalidrawWrapper.style.height = `${st.height}px`;
5502-
this.excalidrawContainer?.querySelector(".App-bottom-bar")?.scrollIntoView();
5503-
this.headerEl?.scrollIntoView();
5504-
}
5533+
console.log("Keyboard open", Date.now());
5534+
const elCenterY = st.editingTextElement.y + st.editingTextElement.height / 2;
5535+
const newScroll = (st.height / st.zoom.value) / 2 - elCenterY;
5536+
this.oldKeyboardScroll = st.scrollY;
5537+
this.updateScene({appState: {scrollY: newScroll}, captureUpdate: CaptureUpdateAction.NEVER});
5538+
this.containerEl.scrollIntoView();
55055539
}
5506-
if(isKeyboardBackEvent) {
5507-
const excalidrawWrapper = this.excalidrawWrapperRef.current;
5508-
const appButtonBar = this.excalidrawContainer?.querySelector(".App-bottom-bar");
5509-
const headerEl = this.headerEl;
5510-
if(excalidrawWrapper) {
5511-
excalidrawWrapper.style.top = "";
5512-
excalidrawWrapper.style.height = "";
5513-
appButtonBar?.scrollIntoView();
5514-
headerEl?.scrollIntoView();
5540+
if (isKeyboardBackEvent) {
5541+
console.log("Keyboard close", Date.now());
5542+
if(this.oldKeyboardScroll != null) {
5543+
this.updateScene({appState: {scrollY: this.oldKeyboardScroll}, captureUpdate: CaptureUpdateAction.NEVER});
5544+
this.oldKeyboardScroll = null;
5545+
this.containerEl.scrollIntoView();
55155546
}
55165547
}
55175548
//end of aweful hack

0 commit comments

Comments
 (0)