mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
fix(editor): android keyboard can not be opened (#10502)
Close [BS-2674](https://linear.app/affine-design/issue/BS-2674/[android]-%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91%E5%8C%BA%E5%9F%9F%E7%82%B9%E5%87%BB%E5%90%8E%E6%97%A0%E6%B3%95%E6%BF%80%E6%B4%BB%E9%94%AE%E7%9B%98) [BS-2609](https://linear.app/affine-design/issue/BS-2609/[android]-%E8%BE%93%E5%85%A5%E7%9A%84-toolbar-%E6%B2%A1%E6%9C%89%E4%BA%86)
This commit is contained in:
@@ -153,6 +153,10 @@ export class DocTitle extends WithDisposable(ShadowlessElement) {
|
||||
return this._richTextElement.inlineEditor;
|
||||
}
|
||||
|
||||
get inlineEditorContainer() {
|
||||
return this._richTextElement.inlineEditorContainer;
|
||||
}
|
||||
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
import { IS_IOS } from '@blocksuite/global/env';
|
||||
import type * as GlobalTypes from '@blocksuite/global/types';
|
||||
import { DisposableGroup } from '@blocksuite/global/utils';
|
||||
import { signal } from '@preact/signals-core';
|
||||
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
||||
|
||||
declare type _GLOBAL_ = typeof GlobalTypes;
|
||||
|
||||
function notSupportedWarning() {
|
||||
console.warn('VirtualKeyboard API and VisualViewport API are not supported');
|
||||
}
|
||||
|
||||
export type VirtualKeyboardControllerConfig = {
|
||||
useScreenHeight: boolean;
|
||||
inputElement: HTMLElement;
|
||||
};
|
||||
|
||||
export class VirtualKeyboardController implements ReactiveController {
|
||||
private readonly _disposables = new DisposableGroup();
|
||||
|
||||
private readonly _keyboardHeight$ = signal(0);
|
||||
|
||||
private readonly _keyboardOpened$ = signal(false);
|
||||
|
||||
private readonly _storeInitialInputElementAttributes = () => {
|
||||
const { inputElement } = this.config;
|
||||
if (navigator.virtualKeyboard) {
|
||||
const { overlaysContent } = navigator.virtualKeyboard;
|
||||
const { virtualKeyboardPolicy } = inputElement;
|
||||
|
||||
this._disposables.add(() => {
|
||||
if (!navigator.virtualKeyboard) return;
|
||||
navigator.virtualKeyboard.overlaysContent = overlaysContent;
|
||||
inputElement.virtualKeyboardPolicy = virtualKeyboardPolicy;
|
||||
});
|
||||
} else if (visualViewport) {
|
||||
const { inputMode } = inputElement;
|
||||
this._disposables.add(() => {
|
||||
inputElement.inputMode = inputMode;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private readonly _updateKeyboardHeight = () => {
|
||||
const { virtualKeyboard } = navigator;
|
||||
if (virtualKeyboard) {
|
||||
this._keyboardOpened$.value = virtualKeyboard.boundingRect.height > 0;
|
||||
this._keyboardHeight$.value = virtualKeyboard.boundingRect.height;
|
||||
} else if (visualViewport) {
|
||||
const windowHeight = this.config.useScreenHeight
|
||||
? window.screen.height
|
||||
: window.innerHeight;
|
||||
|
||||
/**
|
||||
* ┌───────────────┐ - window top
|
||||
* │ │
|
||||
* │ │
|
||||
* │ │
|
||||
* │ │
|
||||
* │ │
|
||||
* └───────────────┘ - keyboard top --
|
||||
* │ │ │ keyboard height in layout viewport
|
||||
* └───────────────┘ - page(html) bottom --
|
||||
* │ │ │ visualViewport.offsetTop
|
||||
* └───────────────┘ - window bottom --
|
||||
*/
|
||||
this._keyboardOpened$.value = windowHeight - visualViewport.height > 0;
|
||||
this._keyboardHeight$.value =
|
||||
windowHeight -
|
||||
visualViewport.height -
|
||||
(IS_IOS ? 0 : visualViewport.offsetTop);
|
||||
} else {
|
||||
notSupportedWarning();
|
||||
}
|
||||
};
|
||||
|
||||
hide = () => {
|
||||
if (navigator.virtualKeyboard) {
|
||||
navigator.virtualKeyboard.hide();
|
||||
} else {
|
||||
this.config.inputElement.inputMode = 'none';
|
||||
}
|
||||
};
|
||||
|
||||
host: ReactiveControllerHost & {
|
||||
virtualKeyboardControllerConfig: VirtualKeyboardControllerConfig;
|
||||
hasUpdated: boolean;
|
||||
};
|
||||
|
||||
show = () => {
|
||||
if (navigator.virtualKeyboard) {
|
||||
navigator.virtualKeyboard.show();
|
||||
} else {
|
||||
this.config.inputElement.inputMode = '';
|
||||
}
|
||||
};
|
||||
|
||||
toggle = () => {
|
||||
if (this.opened) {
|
||||
this.hide();
|
||||
} else {
|
||||
this.show();
|
||||
}
|
||||
};
|
||||
|
||||
get config() {
|
||||
return this.host.virtualKeyboardControllerConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the height of keyboard in layout viewport
|
||||
* see comment in the `_updateKeyboardHeight` method
|
||||
*/
|
||||
get keyboardHeight() {
|
||||
return this._keyboardHeight$.value;
|
||||
}
|
||||
|
||||
get opened() {
|
||||
return this._keyboardOpened$.value;
|
||||
}
|
||||
|
||||
constructor(host: VirtualKeyboardController['host']) {
|
||||
(this.host = host).addController(this);
|
||||
}
|
||||
|
||||
hostConnected() {
|
||||
this._storeInitialInputElementAttributes();
|
||||
|
||||
const { inputElement } = this.config;
|
||||
|
||||
if (navigator.virtualKeyboard) {
|
||||
navigator.virtualKeyboard.overlaysContent = true;
|
||||
this.config.inputElement.virtualKeyboardPolicy = 'manual';
|
||||
|
||||
this._disposables.addFromEvent(
|
||||
navigator.virtualKeyboard,
|
||||
'geometrychange',
|
||||
this._updateKeyboardHeight
|
||||
);
|
||||
} else if (visualViewport) {
|
||||
this._disposables.addFromEvent(
|
||||
visualViewport,
|
||||
'resize',
|
||||
this._updateKeyboardHeight
|
||||
);
|
||||
this._disposables.addFromEvent(
|
||||
visualViewport,
|
||||
'scroll',
|
||||
this._updateKeyboardHeight
|
||||
);
|
||||
} else {
|
||||
notSupportedWarning();
|
||||
}
|
||||
|
||||
this._disposables.addFromEvent(inputElement, 'focus', this.show);
|
||||
this._disposables.addFromEvent(inputElement, 'blur', this.hide);
|
||||
|
||||
this._updateKeyboardHeight();
|
||||
}
|
||||
|
||||
hostDisconnected() {
|
||||
this._disposables.dispose();
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export * from './controller.js';
|
||||
Reference in New Issue
Block a user