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:
@@ -106,15 +106,40 @@ framework.impl(ValidatorProvider, {
|
||||
},
|
||||
});
|
||||
framework.impl(VirtualKeyboardProvider, {
|
||||
addEventListener: (event, callback) => {
|
||||
Keyboard.addListener(event as any, callback as any).catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
},
|
||||
removeAllListeners: () => {
|
||||
Keyboard.removeAllListeners().catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
// We dose not provide show and hide because:
|
||||
// - Keyboard.show() is not implemented
|
||||
// - Keyboard.hide() will blur the current editor
|
||||
onChange: callback => {
|
||||
let disposeRef = {
|
||||
dispose: () => {},
|
||||
};
|
||||
|
||||
Promise.all([
|
||||
Keyboard.addListener('keyboardDidShow', info => {
|
||||
callback({
|
||||
visible: true,
|
||||
height: info.keyboardHeight,
|
||||
});
|
||||
}),
|
||||
Keyboard.addListener('keyboardWillHide', () => {
|
||||
callback({
|
||||
visible: false,
|
||||
height: 0,
|
||||
});
|
||||
}),
|
||||
])
|
||||
.then(handlers => {
|
||||
disposeRef.dispose = () => {
|
||||
Promise.all(handlers.map(handler => handler.remove())).catch(
|
||||
console.error
|
||||
);
|
||||
};
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
return () => {
|
||||
disposeRef.dispose();
|
||||
};
|
||||
},
|
||||
});
|
||||
framework.impl(NavigationGestureProvider, {
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
import type { PluginListenerHandle } from '@capacitor/core/types/definitions';
|
||||
import { Keyboard } from '@capacitor/keyboard';
|
||||
|
||||
type VirtualKeyboardCallback =
|
||||
| (<K extends keyof VirtualKeyboardEventMap>(
|
||||
this: VirtualKeyboard,
|
||||
ev: VirtualKeyboardEventMap[K]
|
||||
) => any)
|
||||
| EventListenerOrEventListenerObject;
|
||||
|
||||
class NavigatorVirtualKeyboard implements VirtualKeyboard {
|
||||
private readonly _boundingRect = new DOMRect();
|
||||
|
||||
private readonly _overlaysContent = false;
|
||||
|
||||
private readonly _listeners = new Map<
|
||||
string,
|
||||
Set<{
|
||||
cb: VirtualKeyboardCallback;
|
||||
options?: boolean | AddEventListenerOptions;
|
||||
}>
|
||||
>();
|
||||
|
||||
private _capacitorListenerHandles: PluginListenerHandle[] = [];
|
||||
|
||||
private async _bindListener() {
|
||||
const updateBoundingRect = (info?: { keyboardHeight: number }) => {
|
||||
this.boundingRect.x = 0;
|
||||
this.boundingRect.y = info ? window.innerHeight - info.keyboardHeight : 0;
|
||||
this.boundingRect.width = window.innerWidth;
|
||||
this.boundingRect.height = info ? info.keyboardHeight : 0;
|
||||
this.dispatchEvent(new Event('geometrychange'));
|
||||
};
|
||||
|
||||
this._capacitorListenerHandles = [
|
||||
await Keyboard.addListener('keyboardDidShow', updateBoundingRect),
|
||||
await Keyboard.addListener('keyboardDidHide', updateBoundingRect),
|
||||
];
|
||||
}
|
||||
|
||||
dispatchEvent = (event: Event) => {
|
||||
const listeners = this._listeners.get(event.type);
|
||||
if (listeners) {
|
||||
for (const l of listeners) {
|
||||
if (typeof l.cb === 'function') {
|
||||
l.cb.call(this, event);
|
||||
} else {
|
||||
l.cb.handleEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
return !(event.cancelable && event.defaultPrevented);
|
||||
};
|
||||
|
||||
constructor() {
|
||||
this._bindListener().catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this._capacitorListenerHandles.forEach(handle => {
|
||||
handle.remove().catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
get boundingRect(): DOMRect {
|
||||
return this._boundingRect;
|
||||
}
|
||||
|
||||
get overlaysContent(): boolean {
|
||||
return this._overlaysContent;
|
||||
}
|
||||
|
||||
set overlaysContent(_: boolean) {
|
||||
console.warn(
|
||||
'overlaysContent is read-only in polyfill based on @capacitor/keyboard'
|
||||
);
|
||||
}
|
||||
|
||||
hide() {
|
||||
Keyboard.hide().catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
}
|
||||
|
||||
show() {
|
||||
Keyboard.show().catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
}
|
||||
|
||||
ongeometrychange: ((this: VirtualKeyboard, ev: Event) => any) | null = null;
|
||||
|
||||
addEventListener<K extends keyof VirtualKeyboardEventMap>(
|
||||
type: K,
|
||||
listener: VirtualKeyboardCallback,
|
||||
options?: boolean | AddEventListenerOptions
|
||||
) {
|
||||
if (!this._listeners.has(type)) {
|
||||
this._listeners.set(type, new Set());
|
||||
}
|
||||
|
||||
const listeners = this._listeners.get(type);
|
||||
if (!listeners) return;
|
||||
|
||||
listeners.add({ cb: listener, options });
|
||||
}
|
||||
|
||||
removeEventListener<K extends keyof VirtualKeyboardEventMap>(
|
||||
type: K,
|
||||
listener: VirtualKeyboardCallback,
|
||||
options?: boolean | EventListenerOptions
|
||||
) {
|
||||
const listeners = this._listeners.get(type);
|
||||
if (!listeners) return;
|
||||
|
||||
const sameCapture = (
|
||||
a?: boolean | AddEventListenerOptions,
|
||||
b?: boolean | EventListenerOptions
|
||||
) => {
|
||||
if (a === undefined && b === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof a === 'boolean' && typeof b === 'boolean') {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
if (typeof a === 'object' && typeof b === 'object') {
|
||||
return a.capture === b.capture;
|
||||
}
|
||||
|
||||
if (typeof a === 'object' && typeof b === 'boolean') {
|
||||
return a.capture === b;
|
||||
}
|
||||
|
||||
if (typeof a === 'boolean' && typeof b === 'object') {
|
||||
return a === b.capture;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
let target = null;
|
||||
for (const l of listeners) {
|
||||
if (l.cb === listener && sameCapture(l.options, options)) {
|
||||
target = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (target) {
|
||||
listeners.delete(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error polyfill
|
||||
navigator.virtualKeyboard = new NavigatorVirtualKeyboard();
|
||||
Reference in New Issue
Block a user