Android task entry fix

This commit is contained in:
2026-03-29 11:27:43 -04:00
parent 2475204000
commit a60af7de31
2 changed files with 78 additions and 27 deletions

45
main.js

File diff suppressed because one or more lines are too long

View File

@ -25,6 +25,7 @@ export class TaskEditorModal extends Modal {
private selectedFile: TFile | null = null; private selectedFile: TFile | null = null;
private fileLabel: HTMLSpanElement | null = null; private fileLabel: HTMLSpanElement | null = null;
private keyboardHandler: (() => void) | null = null; private keyboardHandler: (() => void) | null = null;
private keyboardResetHandler: (() => void) | null = null;
constructor( constructor(
app: App, app: App,
@ -46,20 +47,42 @@ export class TaskEditorModal extends Modal {
const { contentEl } = this; const { contentEl } = this;
contentEl.addClass('yaotp-editor-modal'); contentEl.addClass('yaotp-editor-modal');
// On Android the on-screen keyboard shrinks the visual viewport but not // On Android the on-screen keyboard doesn't resize the layout viewport, so
// the layout viewport, so a fixed-position modal stays centered in the // the fixed-position modal container stays full-height and the modal ends
// full layout height and gets half-covered. We listen for visual-viewport // up centered behind the keyboard. We fix this by:
// resize events and pull the modal container's bottom edge up to match, // 1. On textarea focus (+ a short delay for the keyboard animation),
// keeping the modal in the visible area above the keyboard. // read the visual viewport height and shrink the container to that
if (window.visualViewport) { // size, then align the modal to the top of the container.
this.keyboardHandler = () => { // 2. On blur, reset everything.
const vv = window.visualViewport!; // We also listen to visualViewport and window resize as supplementary
const keyboardHeight = Math.max(0, window.innerHeight - vv.height - vv.offsetTop); // triggers in case the keyboard appears/disappears without a focus change.
this.containerEl.style.bottom = `${keyboardHeight}px`; const adjust = () => {
this.modalEl.style.maxHeight = keyboardHeight > 0 ? `${vv.height * 0.9}px` : ''; const vv = window.visualViewport;
}; const availableHeight = vv ? vv.height : window.innerHeight;
window.visualViewport.addEventListener('resize', this.keyboardHandler); const keyboardHeight = Math.max(0, window.innerHeight - availableHeight);
if (keyboardHeight > 50) {
this.containerEl.style.height = `${availableHeight}px`;
this.containerEl.style.alignItems = 'flex-start';
this.containerEl.style.paddingTop = '8px';
this.modalEl.style.maxHeight = `${availableHeight - 16}px`;
} else {
this.containerEl.style.height = '';
this.containerEl.style.alignItems = '';
this.containerEl.style.paddingTop = '';
this.modalEl.style.maxHeight = '';
} }
};
this.keyboardHandler = adjust;
this.keyboardResetHandler = () => {
this.containerEl.style.height = '';
this.containerEl.style.alignItems = '';
this.containerEl.style.paddingTop = '';
this.modalEl.style.maxHeight = '';
};
window.visualViewport?.addEventListener('resize', adjust);
window.addEventListener('resize', adjust);
// Title // Title
contentEl.createEl('h2', { text: 'Edit task' }); contentEl.createEl('h2', { text: 'Edit task' });
@ -74,6 +97,8 @@ export class TaskEditorModal extends Modal {
attr: { rows: '8', placeholder: 'Task title\n\nNotes…' }, attr: { rows: '8', placeholder: 'Task title\n\nNotes…' },
}); });
this.textarea.value = initialValue; this.textarea.value = initialValue;
this.textarea.addEventListener('focus', () => setTimeout(adjust, 300));
this.textarea.addEventListener('blur', () => setTimeout(adjust, 100));
// Auto-focus // Auto-focus
setTimeout(() => this.textarea?.focus(), 50); setTimeout(() => this.textarea?.focus(), 50);
@ -129,8 +154,11 @@ export class TaskEditorModal extends Modal {
onClose(): void { onClose(): void {
if (this.keyboardHandler) { if (this.keyboardHandler) {
window.visualViewport?.removeEventListener('resize', this.keyboardHandler); window.visualViewport?.removeEventListener('resize', this.keyboardHandler);
window.removeEventListener('resize', this.keyboardHandler);
this.keyboardHandler = null; this.keyboardHandler = null;
} }
this.keyboardResetHandler?.();
this.keyboardResetHandler = null;
this.contentEl.empty(); this.contentEl.empty();
} }